summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Zavialov <vlad.z.4096@gmail.com>2020-10-18 15:24:31 +0300
committerVladislav Zavialov <vlad.z.4096@gmail.com>2022-03-15 18:34:38 +0300
commitab618309069bb47645f33cd1b198ace46e27abb9 (patch)
tree0a388d085a19b16da85dc91cc958578c9a033399
parent8ff32124c8cd37050f3dc7cbb32b8d41711ebcaf (diff)
downloadhaskell-ab618309069bb47645f33cd1b198ace46e27abb9.tar.gz
Export (~) from Data.Type.Equality (#18862)wip/eqtycon-rn
* Users can define their own (~) type operator * Haddock can display documentation for the built-in (~) * New transitional warnings implemented: -Wtype-equality-out-of-scope -Wtype-equality-requires-operators Updates the haddock submodule.
-rw-r--r--compiler/GHC/Builtin/Names.hs3
-rw-r--r--compiler/GHC/Builtin/Types.hs24
-rw-r--r--compiler/GHC/Driver/Flags.hs8
-rw-r--r--compiler/GHC/Driver/Session.hs4
-rw-r--r--compiler/GHC/Parser.y8
-rw-r--r--compiler/GHC/Parser/PostProcess.hs5
-rw-r--r--compiler/GHC/Rename/Env.hs27
-rw-r--r--compiler/GHC/Rename/Expr.hs-boot6
-rw-r--r--compiler/GHC/Rename/HsType.hs22
-rw-r--r--compiler/GHC/Tc/Errors/Ppr.hs29
-rw-r--r--compiler/GHC/Tc/Errors/Types.hs29
-rw-r--r--compiler/GHC/Tc/Validity.hs4
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--docs/users_guide/9.4.1-notes.rst21
-rw-r--r--docs/users_guide/using-warnings.rst44
-rw-r--r--libraries/base/Data/String.hs1
-rw-r--r--libraries/base/Data/Type/Equality.hs4
-rw-r--r--libraries/base/Data/Type/Ord.hs1
-rw-r--r--libraries/base/Prelude.hs3
-rw-r--r--libraries/base/Text/Printf.hs2
-rw-r--r--libraries/ghc-heap/GHC/Exts/Heap.hs2
-rw-r--r--libraries/ghc-prim/GHC/Types.hs3
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs2
-rw-r--r--testsuite/tests/backpack/should_fail/bkpfail23.bkp2
-rw-r--r--testsuite/tests/deriving/should_compile/T14933.hs3
-rw-r--r--testsuite/tests/ghci/scripts/T12447.script2
-rw-r--r--testsuite/tests/ghci/scripts/ghci024.stdout1
-rw-r--r--testsuite/tests/ghci/scripts/ghci024.stdout-mingw321
-rw-r--r--testsuite/tests/indexed-types/should_compile/InstEqContext2.hs2
-rw-r--r--testsuite/tests/indexed-types/should_compile/T11361.hs1
-rw-r--r--testsuite/tests/indexed-types/should_compile/T15122.hs1
-rw-r--r--testsuite/tests/indexed-types/should_compile/T15352.hs1
-rw-r--r--testsuite/tests/parser/should_fail/T12811.stderr2
-rw-r--r--testsuite/tests/parser/should_fail/T15209.stderr4
-rw-r--r--testsuite/tests/partial-sigs/should_fail/T14584.hs1
-rw-r--r--testsuite/tests/partial-sigs/should_fail/T14584.stderr12
-rw-r--r--testsuite/tests/perf/compiler/T3064.hs1
-rw-r--r--testsuite/tests/polykinds/T11523.hs3
-rw-r--r--testsuite/tests/polykinds/T12055.hs4
-rw-r--r--testsuite/tests/quantified-constraints/T15359.hs2
-rw-r--r--testsuite/tests/quantified-constraints/T15359a.hs2
-rw-r--r--testsuite/tests/rebindable/T19167.hs1
-rw-r--r--testsuite/tests/rename/should_compile/T15214.hs (renamed from testsuite/tests/rename/should_fail/T15214.hs)0
-rw-r--r--testsuite/tests/rename/should_compile/T18862.hs12
-rw-r--r--testsuite/tests/rename/should_compile/all.T2
-rw-r--r--testsuite/tests/rename/should_fail/T15214.stderr2
-rw-r--r--testsuite/tests/rename/should_fail/all.T1
-rw-r--r--testsuite/tests/roles/should_compile/Roles3.hs3
-rw-r--r--testsuite/tests/tcplugins/TcPlugin_Rewrite.hs5
-rw-r--r--testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs2
-rw-r--r--testsuite/tests/typecheck/should_compile/T11524.hs1
-rw-r--r--testsuite/tests/typecheck/should_compile/T12919.hs2
-rw-r--r--testsuite/tests/typecheck/should_compile/T13651a.hs2
-rw-r--r--testsuite/tests/typecheck/should_compile/T17202.hs1
-rw-r--r--testsuite/tests/typecheck/should_compile/T17562b.hs2
-rw-r--r--testsuite/tests/typecheck/should_compile/T17567StupidThetaB.hs2
-rw-r--r--testsuite/tests/typecheck/should_compile/T21010A.hs1
-rw-r--r--testsuite/tests/typecheck/should_compile/tc250.hs1
-rw-r--r--testsuite/tests/typecheck/should_compile/tc251.hs1
-rw-r--r--testsuite/tests/typecheck/should_compile/tc252.hs1
-rw-r--r--testsuite/tests/typecheck/should_compile/tc253.hs1
-rw-r--r--testsuite/tests/warnings/should_compile/T18862a.hs6
-rw-r--r--testsuite/tests/warnings/should_compile/T18862a.stderr5
-rw-r--r--testsuite/tests/warnings/should_compile/T18862b.hs8
-rw-r--r--testsuite/tests/warnings/should_compile/T18862b.stderr8
-rw-r--r--testsuite/tests/warnings/should_compile/all.T2
-rw-r--r--utils/check-exact/ExactPrint.hs1
m---------utils/haddock0
68 files changed, 277 insertions, 94 deletions
diff --git a/compiler/GHC/Builtin/Names.hs b/compiler/GHC/Builtin/Names.hs
index 9b1c9bad01..e17f2dda44 100644
--- a/compiler/GHC/Builtin/Names.hs
+++ b/compiler/GHC/Builtin/Names.hs
@@ -2770,4 +2770,5 @@ pretendNameIsInScope n
[ liftedTypeKindTyConKey, unliftedTypeKindTyConKey
, liftedDataConKey, unliftedDataConKey
, tYPETyConKey
- , runtimeRepTyConKey, boxedRepDataConKey ]
+ , runtimeRepTyConKey, boxedRepDataConKey
+ , eqTyConKey ]
diff --git a/compiler/GHC/Builtin/Types.hs b/compiler/GHC/Builtin/Types.hs
index 347afad5c0..54354fcd5f 100644
--- a/compiler/GHC/Builtin/Types.hs
+++ b/compiler/GHC/Builtin/Types.hs
@@ -343,27 +343,6 @@ eqTyConName = mkWiredInTyConName UserSyntax gHC_TYPES (fsLit "~") eqTyConK
eqDataConName = mkWiredInDataConName UserSyntax gHC_TYPES (fsLit "Eq#") eqDataConKey eqDataCon
eqSCSelIdName = mkWiredInIdName gHC_TYPES (fsLit "eq_sel") eqSCSelIdKey eqSCSelId
-{- Note [eqTyCon (~) is built-in syntax]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The (~) type operator used in equality constraints (a~b) is considered built-in
-syntax. This has a few consequences:
-
-* The user is not allowed to define their own type constructors with this name:
-
- ghci> class a ~ b
- <interactive>:1:1: error: Illegal binding of built-in syntax: ~
-
-* Writing (a ~ b) does not require enabling -XTypeOperators. It does, however,
- require -XGADTs or -XTypeFamilies.
-
-* The (~) type operator is always in scope. It doesn't need to be imported,
- and it cannot be hidden.
-
-* We have a bunch of special cases in the compiler to arrange all of the above.
-
-There's no particular reason for (~) to be special, but fixing this would be a
-breaking change.
--}
eqTyCon_RDR :: RdrName
eqTyCon_RDR = nameRdrName eqTyConName
@@ -893,9 +872,6 @@ isBuiltInOcc_maybe occ =
"[]" -> Just $ choose_ns listTyConName nilDataConName
":" -> Just consDataConName
- -- equality tycon
- "~" -> Just eqTyConName
-
-- function tycon
"FUN" -> Just funTyConName
"->" -> Just unrestrictedFunTyConName
diff --git a/compiler/GHC/Driver/Flags.hs b/compiler/GHC/Driver/Flags.hs
index 21649c9c54..1d1222fbab 100644
--- a/compiler/GHC/Driver/Flags.hs
+++ b/compiler/GHC/Driver/Flags.hs
@@ -553,6 +553,8 @@ data WarningFlag =
| Opt_WarnForallIdentifier -- Since 9.4
| Opt_WarnUnicodeBidirectionalFormatCharacters -- Since 9.0.2
| Opt_WarnGADTMonoLocalBinds -- Since 9.4
+ | Opt_WarnTypeEqualityOutOfScope -- Since 9.4
+ | Opt_WarnTypeEqualityRequiresOperators -- Since 9.4
deriving (Eq, Ord, Show, Enum)
-- | Return the names of a WarningFlag
@@ -655,6 +657,8 @@ warnFlagNames wflag = case wflag of
Opt_WarnForallIdentifier -> "forall-identifier" :| []
Opt_WarnUnicodeBidirectionalFormatCharacters -> "unicode-bidirectional-format-characters" :| []
Opt_WarnGADTMonoLocalBinds -> "gadt-mono-local-binds" :| []
+ Opt_WarnTypeEqualityOutOfScope -> "type-equality-out-of-scope" :| []
+ Opt_WarnTypeEqualityRequiresOperators -> "type-equality-requires-operators" :| []
-- -----------------------------------------------------------------------------
-- Standard sets of warning options
@@ -748,7 +752,8 @@ standardWarnings -- see Note [Documenting warning flags]
Opt_WarnOperatorWhitespaceExtConflict,
Opt_WarnForallIdentifier,
Opt_WarnUnicodeBidirectionalFormatCharacters,
- Opt_WarnGADTMonoLocalBinds
+ Opt_WarnGADTMonoLocalBinds,
+ Opt_WarnTypeEqualityRequiresOperators
]
-- | Things you get with -W
@@ -801,6 +806,7 @@ minusWcompatOpts
, Opt_WarnNonCanonicalMonoidInstances
, Opt_WarnStarIsType
, Opt_WarnCompatUnqualifiedImports
+ , Opt_WarnTypeEqualityOutOfScope
]
-- | Things you get with -Wunused-binds
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 49e322bbd2..d62660c519 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -3295,7 +3295,9 @@ wWarningFlagsDeps = mconcat [
warnSpec Opt_WarnMissingExportedPatternSynonymSignatures,
warnSpec Opt_WarnForallIdentifier,
warnSpec Opt_WarnUnicodeBidirectionalFormatCharacters,
- warnSpec Opt_WarnGADTMonoLocalBinds
+ warnSpec Opt_WarnGADTMonoLocalBinds,
+ warnSpec Opt_WarnTypeEqualityOutOfScope,
+ warnSpec Opt_WarnTypeEqualityRequiresOperators
]
-- | These @-\<blah\>@ flags can all be reversed with @-no-\<blah\>@
diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y
index a11a438d89..24ef753453 100644
--- a/compiler/GHC/Parser.y
+++ b/compiler/GHC/Parser.y
@@ -90,7 +90,7 @@ import GHC.Parser.Errors.Ppr ()
import GHC.Builtin.Types ( unitTyCon, unitDataCon, sumTyCon,
tupleTyCon, tupleDataCon, nilDataCon,
unboxedUnitTyCon, unboxedUnitDataCon,
- listTyCon_RDR, consDataCon_RDR, eqTyCon_RDR)
+ listTyCon_RDR, consDataCon_RDR)
import qualified Data.Semigroup as Semi
}
@@ -3641,11 +3641,7 @@ qtyconsym :: { LocatedN RdrName }
tyconsym :: { LocatedN RdrName }
: CONSYM { sL1n $1 $! mkUnqual tcClsName (getCONSYM $1) }
- | VARSYM { sL1n $1 $!
- -- See Note [eqTyCon (~) is built-in syntax] in GHC.Builtin.Types
- if getVARSYM $1 == fsLit "~"
- then eqTyCon_RDR
- else mkUnqual tcClsName (getVARSYM $1) }
+ | VARSYM { sL1n $1 $! mkUnqual tcClsName (getVARSYM $1) }
| ':' { sL1n $1 $! consDataCon_RDR }
| '-' { sL1n $1 $! mkUnqual tcClsName (fsLit "-") }
| '.' { sL1n $1 $! mkUnqual tcClsName (fsLit ".") }
diff --git a/compiler/GHC/Parser/PostProcess.hs b/compiler/GHC/Parser/PostProcess.hs
index e5557855c0..444471abca 100644
--- a/compiler/GHC/Parser/PostProcess.hs
+++ b/compiler/GHC/Parser/PostProcess.hs
@@ -137,7 +137,7 @@ import GHC.Types.TyThing
import GHC.Core.Type ( unrestrictedFunTyCon, Specificity(..) )
import GHC.Builtin.Types( cTupleTyConName, tupleTyCon, tupleDataCon,
nilDataConName, nilDataConKey,
- listTyConName, listTyConKey, eqTyCon_RDR )
+ listTyConName, listTyConKey )
import GHC.Types.ForeignCall
import GHC.Types.SrcLoc
import GHC.Types.Unique ( hasKey )
@@ -2453,8 +2453,7 @@ checkPrecP (L l (_,i)) (L _ ol)
| otherwise = addFatalError $ mkPlainErrorMsgEnvelope l (PsErrPrecedenceOutOfRange i)
where
-- If you change this, consider updating Note [Fixity of (->)] in GHC/Types.hs
- specialOp op = unLoc op `elem` [ eqTyCon_RDR
- , getRdrName unrestrictedFunTyCon ]
+ specialOp op = unLoc op == getRdrName unrestrictedFunTyCon
mkRecConstrOrUpdate
:: Bool
diff --git a/compiler/GHC/Rename/Env.hs b/compiler/GHC/Rename/Env.hs
index cd40ab100a..3525c71f1b 100644
--- a/compiler/GHC/Rename/Env.hs
+++ b/compiler/GHC/Rename/Env.hs
@@ -1047,7 +1047,24 @@ lookupTypeOccRn rdr_name
= do { mb_name <- lookupOccRn_maybe rdr_name
; case mb_name of
Just name -> return name
- Nothing -> lookup_demoted rdr_name }
+ Nothing ->
+ if occName rdr_name == occName eqTyCon_RDR -- See Note [eqTyCon (~) compatibility fallback]
+ then eqTyConName <$ addDiagnostic TcRnTypeEqualityOutOfScope
+ else lookup_demoted rdr_name }
+
+{- Note [eqTyCon (~) compatibility fallback]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Before GHC Proposal #371, the (~) type operator used in type equality
+constraints (a~b) was considered built-in syntax.
+
+This had two implications:
+
+1. Users could use it without importing it from Data.Type.Equality or Prelude.
+2. TypeOperators were not required to use it (it was guarded behind TypeFamilies/GADTs instead)
+
+To ease migration and minimize breakage, we continue to support those usages
+but emit appropriate warnings.
+-}
lookup_demoted :: RdrName -> RnM Name
lookup_demoted rdr_name
@@ -1919,13 +1936,7 @@ dataTcOccs rdr_name
= [rdr_name]
where
occ = rdrNameOcc rdr_name
- rdr_name_tc =
- case rdr_name of
- -- The (~) type operator is always in scope, so we need a special case
- -- for it here, or else :info (~) fails in GHCi.
- -- See Note [eqTyCon (~) is built-in syntax]
- Unqual occ | occNameFS occ == fsLit "~" -> eqTyCon_RDR
- _ -> setRdrNameSpace rdr_name tcName
+ rdr_name_tc = setRdrNameSpace rdr_name tcName
{-
Note [dataTcOccs and Exact Names]
diff --git a/compiler/GHC/Rename/Expr.hs-boot b/compiler/GHC/Rename/Expr.hs-boot
index 58f6bbc874..ca66c8168b 100644
--- a/compiler/GHC/Rename/Expr.hs-boot
+++ b/compiler/GHC/Rename/Expr.hs-boot
@@ -1,6 +1,12 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
module GHC.Rename.Expr where
+
+#if MIN_VERSION_GLASGOW_HASKELL(9,3,0,0)
+import Data.Type.Equality (type (~))
+#endif
+
import GHC.Types.Name
import GHC.Hs
import GHC.Types.Name.Set ( FreeVars )
diff --git a/compiler/GHC/Rename/HsType.hs b/compiler/GHC/Rename/HsType.hs
index bf31991e8f..edda60fbee 100644
--- a/compiler/GHC/Rename/HsType.hs
+++ b/compiler/GHC/Rename/HsType.hs
@@ -629,7 +629,7 @@ rnHsTyKi env (HsTyVar _ ip (L loc rdr_name))
rnHsTyKi env ty@(HsOpTy _ ty1 l_op ty2)
= setSrcSpan (getLocA l_op) $
- do { (l_op', fvs1) <- rnHsTyOp env ty l_op
+ do { (l_op', fvs1) <- rnHsTyOp env (ppr ty) l_op
; fix <- lookupTyFixityRn l_op'
; (ty1', fvs2) <- rnLHsTyKi env ty1
; (ty2', fvs3) <- rnLHsTyKi env ty2
@@ -822,16 +822,15 @@ rnLTyVar (L loc rdr_name)
; return (L loc tyvar) }
--------------
-rnHsTyOp :: Outputable a
- => RnTyKiEnv -> a -> LocatedN RdrName
+rnHsTyOp :: RnTyKiEnv -> SDoc -> LocatedN RdrName
-> RnM (LocatedN Name, FreeVars)
rnHsTyOp env overall_ty (L loc op)
- = do { ops_ok <- xoptM LangExt.TypeOperators
- ; op' <- rnTyVar env op
- ; unless (ops_ok || op' `hasKey` eqTyConKey) $
- addErr $ TcRnUnknownMessage $ mkPlainError noHints (opTyErr op overall_ty)
- ; let l_op' = L loc op'
- ; return (l_op', unitFV op') }
+ = do { op' <- rnTyVar env op
+ ; unlessXOptM LangExt.TypeOperators $
+ if (op' `hasKey` eqTyConKey) -- See [eqTyCon (~) compatibility fallback] in GHC.Rename.Env
+ then addDiagnostic TcRnTypeEqualityRequiresOperators
+ else addErr $ TcRnIllegalTypeOperator overall_ty op
+ ; return (L loc op', unitFV op') }
--------------
checkWildCard :: RnTyKiEnv
@@ -1660,11 +1659,6 @@ warnUnusedForAll doc (L loc tv) used_names
, inHsDocContext doc ]
addDiagnosticAt (locA loc) msg
-opTyErr :: Outputable a => RdrName -> a -> SDoc
-opTyErr op overall_ty
- = hang (text "Illegal operator" <+> quotes (ppr op) <+> text "in type" <+> quotes (ppr overall_ty))
- 2 (text "Use TypeOperators to allow operators in types")
-
{-
************************************************************************
* *
diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs
index ad78cfaf76..2c9b013e17 100644
--- a/compiler/GHC/Tc/Errors/Ppr.hs
+++ b/compiler/GHC/Tc/Errors/Ppr.hs
@@ -651,6 +651,23 @@ instance Diagnostic TcRnMessage where
fsep [ text "The use of" <+> quotes (ppr rdr_name)
<+> text "as an identifier",
text "will become an error in a future GHC release." ]
+ TcRnTypeEqualityOutOfScope
+ -> mkDecorated
+ [ text "The" <+> quotes (text "~") <+> text "operator is out of scope." $$
+ text "Assuming it to stand for an equality constraint."
+ , text "NB:" <+> (quotes (text "~") <+> text "used to be built-in syntax but now is a regular type operator" $$
+ text "exported from Data.Type.Equality and Prelude.") $$
+ text "If you are using a custom Prelude, consider re-exporting it."
+ , text "This will become an error in a future GHC release." ]
+ TcRnTypeEqualityRequiresOperators
+ -> mkSimpleDecorated $
+ fsep [ text "The use of" <+> quotes (text "~")
+ <+> text "without TypeOperators",
+ text "will become an error in a future GHC release." ]
+ TcRnIllegalTypeOperator overall_ty op
+ -> mkSimpleDecorated $
+ text "Illegal operator" <+> quotes (ppr op) <+>
+ text "in type" <+> quotes (ppr overall_ty)
TcRnGADTMonoLocalBinds
-> mkSimpleDecorated $
fsep [ text "Pattern matching on GADTs without MonoLocalBinds"
@@ -920,6 +937,12 @@ instance Diagnostic TcRnMessage where
-> ErrorWithoutFlag
TcRnForallIdentifier {}
-> WarningWithFlag Opt_WarnForallIdentifier
+ TcRnTypeEqualityOutOfScope
+ -> WarningWithFlag Opt_WarnTypeEqualityOutOfScope
+ TcRnTypeEqualityRequiresOperators
+ -> WarningWithFlag Opt_WarnTypeEqualityRequiresOperators
+ TcRnIllegalTypeOperator {}
+ -> ErrorWithoutFlag
TcRnGADTMonoLocalBinds {}
-> WarningWithFlag Opt_WarnGADTMonoLocalBinds
TcRnIncorrectNameSpace {}
@@ -1152,6 +1175,12 @@ instance Diagnostic TcRnMessage where
-> noHints
TcRnForallIdentifier {}
-> [SuggestRenameForall]
+ TcRnTypeEqualityOutOfScope
+ -> noHints
+ TcRnTypeEqualityRequiresOperators
+ -> [suggestExtension LangExt.TypeOperators]
+ TcRnIllegalTypeOperator {}
+ -> [suggestExtension LangExt.TypeOperators]
TcRnGADTMonoLocalBinds {}
-> [suggestAnyExtension [LangExt.GADTs, LangExt.TypeFamilies]]
TcRnIncorrectNameSpace nm is_th_use
diff --git a/compiler/GHC/Tc/Errors/Types.hs b/compiler/GHC/Tc/Errors/Types.hs
index abf574df19..58e984011a 100644
--- a/compiler/GHC/Tc/Errors/Types.hs
+++ b/compiler/GHC/Tc/Errors/Types.hs
@@ -1581,6 +1581,35 @@ data TcRnMessage where
-}
TcRnForallIdentifier :: RdrName -> TcRnMessage
+ {-| TcRnTypeEqualityOutOfScope is a warning (controlled by -Wtype-equality-out-of-scope)
+ that occurs when the type equality (a ~ b) is not in scope.
+
+ Test case: T18862b
+ -}
+ TcRnTypeEqualityOutOfScope :: TcRnMessage
+
+ {-| TcRnTypeEqualityRequiresOperators is a warning (controlled by -Wtype-equality-requires-operators)
+ that occurs when the type equality (a ~ b) is used without the TypeOperators extension.
+
+ Example:
+ {-# LANGUAGE NoTypeOperators #-}
+ f :: (a ~ b) => a -> b
+
+ Test case: T18862a
+ -}
+ TcRnTypeEqualityRequiresOperators :: TcRnMessage
+
+ {-| TcRnIllegalTypeOperator is an error that occurs when a type operator
+ is used without the TypeOperators extension.
+
+ Example:
+ {-# LANGUAGE NoTypeOperators #-}
+ f :: Vec a n -> Vec a m -> Vec a (n + m)
+
+ Test case: T12811
+ -}
+ TcRnIllegalTypeOperator :: !SDoc -> !RdrName -> TcRnMessage
+
{-| TcRnGADTMonoLocalBinds is a warning controlled by -Wgadt-mono-local-binds
that occurs when pattern matching on a GADT when -XMonoLocalBinds is off.
diff --git a/compiler/GHC/Tc/Validity.hs b/compiler/GHC/Tc/Validity.hs
index 1a5f2f6a41..598b07b8c7 100644
--- a/compiler/GHC/Tc/Validity.hs
+++ b/compiler/GHC/Tc/Validity.hs
@@ -1137,7 +1137,9 @@ check_class_pred env dflags ctxt pred cls tys
-- but here we want to treat them as equalities
= -- Equational constraints are valid in all contexts, and
-- we do not need to check e.g. for FlexibleContexts here, so just do nothing
- return ()
+ -- We used to require TypeFamilies/GADTs for equality constraints,
+ -- but not anymore (GHC Proposal #371)
+ return ()
| isIPClass cls
= do { check_arity
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 3aff044b78..5a3794ee37 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -154,6 +154,7 @@ Library
,BangPatterns
,ScopedTypeVariables
,MonoLocalBinds
+ ,TypeOperators
Exposed-Modules:
GHC
diff --git a/docs/users_guide/9.4.1-notes.rst b/docs/users_guide/9.4.1-notes.rst
index a2cced7294..caac4e9362 100644
--- a/docs/users_guide/9.4.1-notes.rst
+++ b/docs/users_guide/9.4.1-notes.rst
@@ -22,9 +22,24 @@ Language
If you want to retain the old behavior, add a (backward-compatible) type signature,
explicitly requesting this unusual quantification.
-- GHC no longer checks for ``-XGADTs`` or ``-XTypeFamilies`` in order to use
- an equality constraint in a type. This is part of accepted proposal
- `#371 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0371-non-magical-eq.md>`_.
+- GHC Proposal `#371 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0371-non-magical-eq.md>`_ has been implemented. This means:
+
+ * The use of equality constraints no longer requires ``-XGADTs`` or ``-XTypeFamilies``.
+
+ * The use of equality constraint syntax ``a ~ b`` requires ``-XTypeOperators``,
+ otherwise results in a warning (:ghc-flag:`-Wtype-equality-requires-operators`).
+
+ * ``(~)`` is now a legal name for a user-defined type operator:
+ ::
+
+ class a ~ b where
+ ...
+
+ This used to be rejected with "Illegal binding of built-in syntax".
+
+ * The built-in type equality is now exported from ``Data.Type.Equality`` and
+ re-exported from ``Prelude``. When ``(~)`` is not in scope, its use results
+ in a warning (:ghc-flag:`-Wtype-equality-out-of-scope`).
- There were previously cases around functional dependencies and injective
type families where the result of type inference would depend on the order
diff --git a/docs/users_guide/using-warnings.rst b/docs/users_guide/using-warnings.rst
index 5b0093b650..5b2c85099b 100644
--- a/docs/users_guide/using-warnings.rst
+++ b/docs/users_guide/using-warnings.rst
@@ -65,6 +65,7 @@ To reverse ``-Werror``, which makes all warnings into errors, use ``-Wwarn``.
* :ghc-flag:`-Wunicode-bidirectional-format-characters`
* :ghc-flag:`-Wforall-identifier`
* :ghc-flag:`-Wgadt-mono-local-binds`
+ * :ghc-flag:`-Wtype-equality-requires-operators`
The following flags are simple ways to select standard "packages" of warnings:
@@ -161,6 +162,7 @@ The following flags are simple ways to select standard "packages" of warnings:
* :ghc-flag:`-Wnoncanonical-monoid-instances`
* :ghc-flag:`-Wstar-is-type`
* :ghc-flag:`-Wcompat-unqualified-imports`
+ * :ghc-flag:`-Wtype-equality-out-of-scope`
.. ghc-flag:: -Wno-compat
:shortdesc: Disables all warnings enabled by :ghc-flag:`-Wcompat`.
@@ -2286,6 +2288,48 @@ of ``-W(no-)*``.
to pattern match on a GADT if neither :extension:`GADTs`
nor :extension:`TypeFamilies` were enabled.
+.. ghc-flag:: -Wtype-equality-out-of-scope
+ :shortdesc: warn when type equality ``a ~ b`` is used despite being out of scope
+ :type: dynamic
+ :reverse: -Wno-type-equality-out-of-scope
+
+ :since: 9.4.1
+
+ In accordance with `GHC Proposal #371
+ <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0371-non-magical-eq.md>`__,
+ the type equality syntax ``a ~ b`` is no longer built-in. Instead, ``~`` is
+ a regular type operator that can be imported from ``Data.Type.Equality`` or
+ ``Prelude``.
+
+ To minimize breakage, a compatibility fallback is provided: whenever ``~``
+ is used but is not in scope, the compiler assumes that it stands for a type
+ equality constraint. The warning is triggered by any code that relies on
+ this fallback. It can be addressed by bringing ``~`` into scope explicitly.
+
+ The likely culprit is that you use :extension:`NoImplicitPrelude` and a
+ custom Prelude. In this case, consider updating your custom Prelude to
+ re-export ``~`` from ``Data.Type.Equality``.
+
+ Being part of the :ghc-flag:`-Wcompat` option group, this warning is off by
+ default, but will be switched on in a future GHC release.
+
+.. ghc-flag:: -Wtype-equality-requires-operators
+ :shortdesc: warn when type equality ``a ~ b`` is used despite being out of scope
+ :type: dynamic
+ :reverse: -Wno-type-equality-requires-operators
+
+ :since: 9.4.1
+
+ In accordance with `GHC Proposal #371
+ <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0371-non-magical-eq.md>`__,
+ the type equality syntax ``a ~ b`` is no longer built-in. Instead, ``~`` is
+ a regular type operator that requires the :extension:`TypeOperators` extension.
+
+ To minimize breakage, ``~`` specifically (unlike other type operators) can
+ be used even when :extension:`TypeOperators` is disabled. The warning is
+ triggered whenever this happens, and can be addressed by enabling the
+ extension.
+
If you're feeling really paranoid, the :ghc-flag:`-dcore-lint` option is a good choice.
It turns on heavyweight intra-pass sanity-checking within GHC. (It checks GHC's
sanity, not yours.)
diff --git a/libraries/base/Data/String.hs b/libraries/base/Data/String.hs
index 02a720f8e9..bd5d3d0edd 100644
--- a/libraries/base/Data/String.hs
+++ b/libraries/base/Data/String.hs
@@ -5,6 +5,7 @@
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
-----------------------------------------------------------------------------
-- |
diff --git a/libraries/base/Data/Type/Equality.hs b/libraries/base/Data/Type/Equality.hs
index 56cdce77f0..3b11add5f0 100644
--- a/libraries/base/Data/Type/Equality.hs
+++ b/libraries/base/Data/Type/Equality.hs
@@ -31,7 +31,9 @@
module Data.Type.Equality (
-- * The equality types
- (:~:)(..), type (~~),
+ type (~),
+ type (~~),
+ (:~:)(..),
(:~~:)(..),
-- * Working with equality
diff --git a/libraries/base/Data/Type/Ord.hs b/libraries/base/Data/Type/Ord.hs
index 7e9ef24c84..4faf106741 100644
--- a/libraries/base/Data/Type/Ord.hs
+++ b/libraries/base/Data/Type/Ord.hs
@@ -38,6 +38,7 @@ import GHC.Show(Show(..))
import GHC.TypeError
import GHC.TypeLits.Internal
import GHC.TypeNats.Internal
+import GHC.Types (type (~))
import Data.Bool
import Data.Char(Char)
import Data.Eq
diff --git a/libraries/base/Prelude.hs b/libraries/base/Prelude.hs
index 66ea603e72..2e21888abc 100644
--- a/libraries/base/Prelude.hs
+++ b/libraries/base/Prelude.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE ExplicitNamespaces #-}
-----------------------------------------------------------------------------
-- |
@@ -159,6 +160,8 @@ module Prelude (
-- ** Exception handling in the I\/O monad
IOError, ioError, userError,
+ -- ** The equality types
+ type (~)
) where
import Control.Monad
diff --git a/libraries/base/Text/Printf.hs b/libraries/base/Text/Printf.hs
index 4fa9fd7720..397f916265 100644
--- a/libraries/base/Text/Printf.hs
+++ b/libraries/base/Text/Printf.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE Safe #-}
-{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
-----------------------------------------------------------------------------
diff --git a/libraries/ghc-heap/GHC/Exts/Heap.hs b/libraries/ghc-heap/GHC/Exts/Heap.hs
index a587739813..618419ee1f 100644
--- a/libraries/ghc-heap/GHC/Exts/Heap.hs
+++ b/libraries/ghc-heap/GHC/Exts/Heap.hs
@@ -1,7 +1,7 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
-
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeFamilies #-}
diff --git a/libraries/ghc-prim/GHC/Types.hs b/libraries/ghc-prim/GHC/Types.hs
index 145b5ff179..4c6a3c6a17 100644
--- a/libraries/ghc-prim/GHC/Types.hs
+++ b/libraries/ghc-prim/GHC/Types.hs
@@ -37,7 +37,7 @@ module GHC.Types (
Any,
-- * Type equality
- type (~~), Coercible,
+ type (~), type (~~), Coercible,
-- * Representation polymorphism
TYPE, Levity(..), RuntimeRep(..),
@@ -254,7 +254,6 @@ newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
* *
(~) and Coercible
- NB: (~) is built-in syntax, and hence not explicitly exported
* *
********************************************************************* -}
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index 5823cfafa8..3d3f46d2c4 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -2,7 +2,7 @@
DeriveGeneric, FlexibleInstances, DefaultSignatures,
RankNTypes, RoleAnnotations, ScopedTypeVariables,
MagicHash, KindSignatures, PolyKinds, TypeApplications, DataKinds,
- GADTs, UnboxedTuples, UnboxedSums, TypeInType,
+ GADTs, UnboxedTuples, UnboxedSums, TypeInType, TypeOperators,
Trustworthy, DeriveFunctor #-}
{-# OPTIONS_GHC -fno-warn-inline-rule-shadowing #-}
diff --git a/testsuite/tests/backpack/should_fail/bkpfail23.bkp b/testsuite/tests/backpack/should_fail/bkpfail23.bkp
index 831ce42c72..55e533390c 100644
--- a/testsuite/tests/backpack/should_fail/bkpfail23.bkp
+++ b/testsuite/tests/backpack/should_fail/bkpfail23.bkp
@@ -1,5 +1,5 @@
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE GADTs, RoleAnnotations #-}
+{-# LANGUAGE GADTs, TypeOperators, RoleAnnotations #-}
unit p where
signature H where
type role F phantom
diff --git a/testsuite/tests/deriving/should_compile/T14933.hs b/testsuite/tests/deriving/should_compile/T14933.hs
index 5ab808365f..854f5f717a 100644
--- a/testsuite/tests/deriving/should_compile/T14933.hs
+++ b/testsuite/tests/deriving/should_compile/T14933.hs
@@ -2,9 +2,12 @@
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
module T14933 where
import Data.Kind (Type)
+import Data.Type.Equality (type (~))
class Wrapped s where
type Unwrapped s :: Type
diff --git a/testsuite/tests/ghci/scripts/T12447.script b/testsuite/tests/ghci/scripts/T12447.script
index 826dec0b63..3a30c65905 100644
--- a/testsuite/tests/ghci/scripts/T12447.script
+++ b/testsuite/tests/ghci/scripts/T12447.script
@@ -1,5 +1,5 @@
:set -XHaskell2010
-:set -XRankNTypes -XConstraintKinds -XTypeApplications
+:set -XRankNTypes -XConstraintKinds -XTypeApplications -XTypeOperators
import Data.Typeable
diff --git a/testsuite/tests/ghci/scripts/ghci024.stdout b/testsuite/tests/ghci/scripts/ghci024.stdout
index 20750f5817..db6a7b955e 100644
--- a/testsuite/tests/ghci/scripts/ghci024.stdout
+++ b/testsuite/tests/ghci/scripts/ghci024.stdout
@@ -16,6 +16,7 @@ warning settings:
-Wsemigroup
-Wstar-is-type
-Wcompat-unqualified-imports
+ -Wtype-equality-out-of-scope
~~~~~~~~~~ Testing :set -a
options currently set: none.
base language is: GHC2021
diff --git a/testsuite/tests/ghci/scripts/ghci024.stdout-mingw32 b/testsuite/tests/ghci/scripts/ghci024.stdout-mingw32
index 1c03e5fab8..a693b73aaf 100644
--- a/testsuite/tests/ghci/scripts/ghci024.stdout-mingw32
+++ b/testsuite/tests/ghci/scripts/ghci024.stdout-mingw32
@@ -15,6 +15,7 @@ warning settings:
-Wsemigroup
-Wstar-is-type
-Wcompat-unqualified-imports
+ -Wtype-equality-out-of-scope
~~~~~~~~~~ Testing :set -a
options currently set: none.
base language is: GHC2021
diff --git a/testsuite/tests/indexed-types/should_compile/InstEqContext2.hs b/testsuite/tests/indexed-types/should_compile/InstEqContext2.hs
index ea356a44ad..f693837354 100644
--- a/testsuite/tests/indexed-types/should_compile/InstEqContext2.hs
+++ b/testsuite/tests/indexed-types/should_compile/InstEqContext2.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
-{-# LANGUAGE TypeFamilies, EmptyDataDecls #-}
+{-# LANGUAGE TypeFamilies, TypeOperators, EmptyDataDecls #-}
module InstEqContext2 where
diff --git a/testsuite/tests/indexed-types/should_compile/T11361.hs b/testsuite/tests/indexed-types/should_compile/T11361.hs
index 7534734790..d2dc75fe8f 100644
--- a/testsuite/tests/indexed-types/should_compile/T11361.hs
+++ b/testsuite/tests/indexed-types/should_compile/T11361.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- this is needed because |FamHelper a x| /< |Fam a x|
-- This file compiled with -dunique-increment=-1 made GHC crash before
diff --git a/testsuite/tests/indexed-types/should_compile/T15122.hs b/testsuite/tests/indexed-types/should_compile/T15122.hs
index 49a3de642d..1730f3a826 100644
--- a/testsuite/tests/indexed-types/should_compile/T15122.hs
+++ b/testsuite/tests/indexed-types/should_compile/T15122.hs
@@ -1,6 +1,7 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
module T15122 where
diff --git a/testsuite/tests/indexed-types/should_compile/T15352.hs b/testsuite/tests/indexed-types/should_compile/T15352.hs
index 25c4640809..0bb4a2bc63 100644
--- a/testsuite/tests/indexed-types/should_compile/T15352.hs
+++ b/testsuite/tests/indexed-types/should_compile/T15352.hs
@@ -2,6 +2,7 @@
{-# LANGUAGE TypeInType #-} -- or PolyKinds
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
module T15352 where
diff --git a/testsuite/tests/parser/should_fail/T12811.stderr b/testsuite/tests/parser/should_fail/T12811.stderr
index 3dbf6bc342..ec4c79bef9 100644
--- a/testsuite/tests/parser/should_fail/T12811.stderr
+++ b/testsuite/tests/parser/should_fail/T12811.stderr
@@ -1,6 +1,6 @@
T12811.hs:5:15: error:
Illegal operator ‘.’ in type ‘foral a . a’
- Use TypeOperators to allow operators in types
+ Suggested fix: Perhaps you intended to use TypeOperators
T12811.hs:5:15: error: Not in scope: type constructor or class ‘.’
diff --git a/testsuite/tests/parser/should_fail/T15209.stderr b/testsuite/tests/parser/should_fail/T15209.stderr
index 9d1e151cf2..fe1666c37e 100644
--- a/testsuite/tests/parser/should_fail/T15209.stderr
+++ b/testsuite/tests/parser/should_fail/T15209.stderr
@@ -1,2 +1,4 @@
-T15209.hs:6:10: error: Not in scope: type constructor or class ‘~#’
+T15209.hs:6:10: error:
+ Not in scope: type constructor or class ‘~#’
+ Suggested fix: Perhaps use ‘~’ (imported from Prelude)
diff --git a/testsuite/tests/partial-sigs/should_fail/T14584.hs b/testsuite/tests/partial-sigs/should_fail/T14584.hs
index 1615b26205..077c80c490 100644
--- a/testsuite/tests/partial-sigs/should_fail/T14584.hs
+++ b/testsuite/tests/partial-sigs/should_fail/T14584.hs
@@ -25,6 +25,7 @@ module T14584 where
import Data.Monoid
import Data.Kind
+import Data.Type.Equality
data family Sing (a::k)
diff --git a/testsuite/tests/partial-sigs/should_fail/T14584.stderr b/testsuite/tests/partial-sigs/should_fail/T14584.stderr
index 7a47f25967..2cc457e635 100644
--- a/testsuite/tests/partial-sigs/should_fail/T14584.stderr
+++ b/testsuite/tests/partial-sigs/should_fail/T14584.stderr
@@ -1,25 +1,25 @@
-T14584.hs:56:50: warning: [-Wdeferred-type-errors (in -Wdefault)]
+T14584.hs:57:50: warning: [-Wdeferred-type-errors (in -Wdefault)]
• Could not deduce (m1 ~ *)
from the context: (Action act, Monoid a, Good m1)
- bound by the instance declaration at T14584.hs:54:10-89
+ bound by the instance declaration at T14584.hs:55:10-89
‘m1’ is a rigid type variable bound by
the instance declaration
- at T14584.hs:54:10-89
+ at T14584.hs:55:10-89
• In the type ‘a’
In the second argument of ‘fromSing’, namely
‘(sing @m @a :: Sing _)’
In the fourth argument of ‘act’, namely
‘(fromSing @m (sing @m @a :: Sing _))’
-T14584.hs:56:60: warning: [-Wpartial-type-signatures (in -Wdefault)]
+T14584.hs:57:60: warning: [-Wpartial-type-signatures (in -Wdefault)]
• Found type wildcard ‘_’ standing for ‘a0 :: m’
Where: ‘a0’ is an ambiguous type variable
‘m’ is a rigid type variable bound by
the instance declaration
- at T14584.hs:54:10-89
+ at T14584.hs:55:10-89
• In the first argument of ‘Sing’, namely ‘_’
In the type ‘Sing _’
In an expression type signature: Sing _
• Relevant bindings include
- monHom :: a -> a (bound at T14584.hs:56:3)
+ monHom :: a -> a (bound at T14584.hs:57:3)
diff --git a/testsuite/tests/perf/compiler/T3064.hs b/testsuite/tests/perf/compiler/T3064.hs
index af3dc2cde7..b0eba0bad2 100644
--- a/testsuite/tests/perf/compiler/T3064.hs
+++ b/testsuite/tests/perf/compiler/T3064.hs
@@ -2,6 +2,7 @@
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
{-# LANGUAGE Rank2Types, TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE TypeFamilies, GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TypeOperators #-}
module T3064 where
import Control.Applicative
diff --git a/testsuite/tests/polykinds/T11523.hs b/testsuite/tests/polykinds/T11523.hs
index 97551b2208..679d1d13d5 100644
--- a/testsuite/tests/polykinds/T11523.hs
+++ b/testsuite/tests/polykinds/T11523.hs
@@ -19,7 +19,8 @@
module T11523 where
-import GHC.Types (Constraint, Type)
+import Data.Kind (Constraint, Type)
+import Data.Type.Equality (type (~))
import qualified Prelude
type Cat i = i -> i -> Type
diff --git a/testsuite/tests/polykinds/T12055.hs b/testsuite/tests/polykinds/T12055.hs
index de3ad455ea..72c208d77d 100644
--- a/testsuite/tests/polykinds/T12055.hs
+++ b/testsuite/tests/polykinds/T12055.hs
@@ -17,8 +17,8 @@
module T12055 where
-import GHC.Base ( Constraint, Type )
-import GHC.Exts ( type (~~) )
+import Data.Kind (Constraint, Type)
+import Data.Type.Equality (type (~), type (~~))
type Cat k = k -> k -> Type
diff --git a/testsuite/tests/quantified-constraints/T15359.hs b/testsuite/tests/quantified-constraints/T15359.hs
index 2a58d89c05..ca84c0e8be 100644
--- a/testsuite/tests/quantified-constraints/T15359.hs
+++ b/testsuite/tests/quantified-constraints/T15359.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE MultiParamTypeClasses, GADTs, RankNTypes,
- ConstraintKinds, QuantifiedConstraints #-}
+ ConstraintKinds, QuantifiedConstraints, TypeOperators #-}
module T15359 where
diff --git a/testsuite/tests/quantified-constraints/T15359a.hs b/testsuite/tests/quantified-constraints/T15359a.hs
index a5b16acf75..277793b81c 100644
--- a/testsuite/tests/quantified-constraints/T15359a.hs
+++ b/testsuite/tests/quantified-constraints/T15359a.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE MultiParamTypeClasses, GADTs, RankNTypes,
- ConstraintKinds, QuantifiedConstraints,
+ ConstraintKinds, QuantifiedConstraints, TypeOperators,
UndecidableInstances #-}
module T15359a where
diff --git a/testsuite/tests/rebindable/T19167.hs b/testsuite/tests/rebindable/T19167.hs
index 6f7ebff33d..4e98e815ea 100644
--- a/testsuite/tests/rebindable/T19167.hs
+++ b/testsuite/tests/rebindable/T19167.hs
@@ -6,6 +6,7 @@ module Bug where
import qualified Prelude as P
import qualified GHC.Exts as P
import Data.List.NonEmpty ( NonEmpty )
+import Data.Type.Equality ( type (~) )
fromInteger :: P.Integer -> forall a. P.Num a => a
fromInteger n = P.fromInteger n
diff --git a/testsuite/tests/rename/should_fail/T15214.hs b/testsuite/tests/rename/should_compile/T15214.hs
index 55f15593be..55f15593be 100644
--- a/testsuite/tests/rename/should_fail/T15214.hs
+++ b/testsuite/tests/rename/should_compile/T15214.hs
diff --git a/testsuite/tests/rename/should_compile/T18862.hs b/testsuite/tests/rename/should_compile/T18862.hs
new file mode 100644
index 0000000000..7356a27ad8
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/T18862.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE PolyKinds, DataKinds, TypeOperators, TypeFamilies #-}
+
+module T18862 where
+
+import Prelude (Bool)
+import Data.Kind (Constraint)
+import qualified Data.Type.Equality as E
+
+type family (a :: k) ~ (b :: k) :: result_kind
+
+type instance a ~ b = (a E.~ b :: Constraint)
+type instance a ~ b = (a E.== b :: Bool)
diff --git a/testsuite/tests/rename/should_compile/all.T b/testsuite/tests/rename/should_compile/all.T
index 536c5b9013..3a6fdceac3 100644
--- a/testsuite/tests/rename/should_compile/all.T
+++ b/testsuite/tests/rename/should_compile/all.T
@@ -161,6 +161,7 @@ test('T14881', [], multimod_compile, ['T14881', '-W'])
test('T14487', [], multimod_compile, ['T14487', '-v0'])
test('T14747', [], multimod_compile, ['T14747', '-v0'])
test('T15149', [], multimod_compile, ['T15149', '-v0'])
+test('T15214', normal, compile, [''])
test('T13064', normal, compile, [''])
test('T15994', [], makefile_test, ['T15994'])
test('T15798a', normal, compile, [''])
@@ -184,3 +185,4 @@ test('T20609a', normal, compile, [''])
test('T20609b', normal, compile, [''])
test('T20609c', normal, compile, [''])
test('T20609d', normal, compile, [''])
+test('T18862', normal, compile, [''])
diff --git a/testsuite/tests/rename/should_fail/T15214.stderr b/testsuite/tests/rename/should_fail/T15214.stderr
deleted file mode 100644
index 399438adb5..0000000000
--- a/testsuite/tests/rename/should_fail/T15214.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-
-T15214.hs:4:1: error: Illegal binding of built-in syntax: ~
diff --git a/testsuite/tests/rename/should_fail/all.T b/testsuite/tests/rename/should_fail/all.T
index 4ce00de399..5e62e28847 100644
--- a/testsuite/tests/rename/should_fail/all.T
+++ b/testsuite/tests/rename/should_fail/all.T
@@ -137,7 +137,6 @@ test('T14307', normal, compile_fail, [''])
test('T14591', normal, compile_fail, [''])
test('T14907a', normal, compile_fail, [''])
test('T14907b', normal, compile_fail, [''])
-test('T15214', normal, compile_fail, [''])
test('T15539', normal, compile_fail, [''])
test('T15487', normal, multimod_compile_fail, ['T15487','-v0'])
test('T15659', normal, compile_fail, [''])
diff --git a/testsuite/tests/roles/should_compile/Roles3.hs b/testsuite/tests/roles/should_compile/Roles3.hs
index b71d9cf2ec..b79129162e 100644
--- a/testsuite/tests/roles/should_compile/Roles3.hs
+++ b/testsuite/tests/roles/should_compile/Roles3.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE AllowAmbiguousTypes #-} -- meth3, meth4 are ambiguous
module Roles3 where
@@ -20,4 +21,4 @@ class C4 a b where
meth4 :: a -> F4 b -> F4 b
type Syn1 a = F4 a
-type Syn2 a = [a] \ No newline at end of file
+type Syn2 a = [a]
diff --git a/testsuite/tests/tcplugins/TcPlugin_Rewrite.hs b/testsuite/tests/tcplugins/TcPlugin_Rewrite.hs
index 6df19b7b62..5cacd28618 100644
--- a/testsuite/tests/tcplugins/TcPlugin_Rewrite.hs
+++ b/testsuite/tests/tcplugins/TcPlugin_Rewrite.hs
@@ -2,13 +2,16 @@
{-# OPTIONS_GHC -fplugin RewritePlugin #-}
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeFamilies #-}
+{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeFamilies, TypeOperators #-}
module TcPlugin_Rewrite where
import Data.Kind
( Type )
+import Data.Type.Equality
+ ( type (~) )
+
import Definitions
( Add, Nat(..) )
diff --git a/testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs b/testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs
index fd37ede0db..43063d20aa 100644
--- a/testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs
+++ b/testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE RankNTypes, TypeFamilies, FlexibleInstances #-}
+{-# LANGUAGE RankNTypes, TypeFamilies, TypeOperators, FlexibleInstances #-}
{-# OPTIONS_GHC -Wno-missing-methods -Wno-unused-matches #-}
module LocalGivenEqs where
diff --git a/testsuite/tests/typecheck/should_compile/T11524.hs b/testsuite/tests/typecheck/should_compile/T11524.hs
index 0856afe50b..a8c40c88c6 100644
--- a/testsuite/tests/typecheck/should_compile/T11524.hs
+++ b/testsuite/tests/typecheck/should_compile/T11524.hs
@@ -3,6 +3,7 @@
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeOperators #-}
module T11524 where
diff --git a/testsuite/tests/typecheck/should_compile/T12919.hs b/testsuite/tests/typecheck/should_compile/T12919.hs
index 29eb9dc469..825b7f65c1 100644
--- a/testsuite/tests/typecheck/should_compile/T12919.hs
+++ b/testsuite/tests/typecheck/should_compile/T12919.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, GADTs, ConstraintKinds #-}
+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, GADTs, ConstraintKinds, TypeOperators #-}
module T12919 where
diff --git a/testsuite/tests/typecheck/should_compile/T13651a.hs b/testsuite/tests/typecheck/should_compile/T13651a.hs
index f08407b738..80cda684e1 100644
--- a/testsuite/tests/typecheck/should_compile/T13651a.hs
+++ b/testsuite/tests/typecheck/should_compile/T13651a.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
+{-# LANGUAGE TypeFamilies, TypeFamilyDependencies, TypeOperators #-}
module T13651 where
type family F r s = f | f -> r s
diff --git a/testsuite/tests/typecheck/should_compile/T17202.hs b/testsuite/tests/typecheck/should_compile/T17202.hs
index cda5783ec9..ee639b9cc0 100644
--- a/testsuite/tests/typecheck/should_compile/T17202.hs
+++ b/testsuite/tests/typecheck/should_compile/T17202.hs
@@ -2,6 +2,7 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
module T17202 where
diff --git a/testsuite/tests/typecheck/should_compile/T17562b.hs b/testsuite/tests/typecheck/should_compile/T17562b.hs
index b73e6b1bc7..44eb03ce97 100644
--- a/testsuite/tests/typecheck/should_compile/T17562b.hs
+++ b/testsuite/tests/typecheck/should_compile/T17562b.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE QuantifiedConstraints, MultiParamTypeClasses, TypeFamilies #-}
+{-# LANGUAGE QuantifiedConstraints, MultiParamTypeClasses, TypeFamilies, TypeOperators #-}
-- NB: No PolyKinds
module T17562b where
diff --git a/testsuite/tests/typecheck/should_compile/T17567StupidThetaB.hs b/testsuite/tests/typecheck/should_compile/T17567StupidThetaB.hs
index d555511004..1d397f9861 100644
--- a/testsuite/tests/typecheck/should_compile/T17567StupidThetaB.hs
+++ b/testsuite/tests/typecheck/should_compile/T17567StupidThetaB.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE Haskell2010 #-}
-{-# LANGUAGE QuantifiedConstraints, DatatypeContexts, TypeFamilies #-}
+{-# LANGUAGE QuantifiedConstraints, DatatypeContexts, TypeFamilies, TypeOperators #-}
-- NB: -XNoPolyKinds, to get defaulting.
module T17567StupidThetaB where
diff --git a/testsuite/tests/typecheck/should_compile/T21010A.hs b/testsuite/tests/typecheck/should_compile/T21010A.hs
index 234e1c72d7..5e8ef6fe96 100644
--- a/testsuite/tests/typecheck/should_compile/T21010A.hs
+++ b/testsuite/tests/typecheck/should_compile/T21010A.hs
@@ -2,6 +2,7 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
module T21010A ( WrapMono, Constrained(..), withMonoCoercible ) where
import T21010B ( WrapMono(..), withMonoCoercible )
diff --git a/testsuite/tests/typecheck/should_compile/tc250.hs b/testsuite/tests/typecheck/should_compile/tc250.hs
index 445d702b69..1076fc5f49 100644
--- a/testsuite/tests/typecheck/should_compile/tc250.hs
+++ b/testsuite/tests/typecheck/should_compile/tc250.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
module ShouldCompile where
import Data.Kind (Type)
diff --git a/testsuite/tests/typecheck/should_compile/tc251.hs b/testsuite/tests/typecheck/should_compile/tc251.hs
index e9315263af..1c69c1d9ac 100644
--- a/testsuite/tests/typecheck/should_compile/tc251.hs
+++ b/testsuite/tests/typecheck/should_compile/tc251.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
module ShouldCompile where
import Tc251_Help
diff --git a/testsuite/tests/typecheck/should_compile/tc252.hs b/testsuite/tests/typecheck/should_compile/tc252.hs
index 1ad9c7c514..6ff23e75e4 100644
--- a/testsuite/tests/typecheck/should_compile/tc252.hs
+++ b/testsuite/tests/typecheck/should_compile/tc252.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
module ShouldCompile where
import Data.Kind (Type)
diff --git a/testsuite/tests/typecheck/should_compile/tc253.hs b/testsuite/tests/typecheck/should_compile/tc253.hs
index 7553b756a8..5c032daa01 100644
--- a/testsuite/tests/typecheck/should_compile/tc253.hs
+++ b/testsuite/tests/typecheck/should_compile/tc253.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- this is needed because |FamHelper a x| /< |Fam a x|
module ShouldCompile where
diff --git a/testsuite/tests/warnings/should_compile/T18862a.hs b/testsuite/tests/warnings/should_compile/T18862a.hs
new file mode 100644
index 0000000000..532cd83e83
--- /dev/null
+++ b/testsuite/tests/warnings/should_compile/T18862a.hs
@@ -0,0 +1,6 @@
+{-# LANGUAGE NoTypeOperators #-}
+
+module T18862a where
+
+f :: (a ~ b) => a -> b
+f = id
diff --git a/testsuite/tests/warnings/should_compile/T18862a.stderr b/testsuite/tests/warnings/should_compile/T18862a.stderr
new file mode 100644
index 0000000000..e2a6fe3f3c
--- /dev/null
+++ b/testsuite/tests/warnings/should_compile/T18862a.stderr
@@ -0,0 +1,5 @@
+
+T18862a.hs:5:9: warning: [-Wtype-equality-requires-operators (in -Wdefault)]
+ The use of ‘~’ without TypeOperators
+ will become an error in a future GHC release.
+ Suggested fix: Perhaps you intended to use TypeOperators
diff --git a/testsuite/tests/warnings/should_compile/T18862b.hs b/testsuite/tests/warnings/should_compile/T18862b.hs
new file mode 100644
index 0000000000..7259547b7c
--- /dev/null
+++ b/testsuite/tests/warnings/should_compile/T18862b.hs
@@ -0,0 +1,8 @@
+{-# OPTIONS -Wcompat -Wno-error=type-equality-out-of-scope #-}
+
+module T18862b where
+
+import Prelude (id)
+
+f :: (a ~ b) => a -> b
+f = id
diff --git a/testsuite/tests/warnings/should_compile/T18862b.stderr b/testsuite/tests/warnings/should_compile/T18862b.stderr
new file mode 100644
index 0000000000..ac959be7d8
--- /dev/null
+++ b/testsuite/tests/warnings/should_compile/T18862b.stderr
@@ -0,0 +1,8 @@
+
+T18862b.hs:7:9: warning: [-Wtype-equality-out-of-scope (in -Wcompat)]
+ • The ‘~’ operator is out of scope.
+ Assuming it to stand for an equality constraint.
+ • NB: ‘~’ used to be built-in syntax but now is a regular type operator
+ exported from Data.Type.Equality and Prelude.
+ If you are using a custom Prelude, consider re-exporting it.
+ • This will become an error in a future GHC release.
diff --git a/testsuite/tests/warnings/should_compile/all.T b/testsuite/tests/warnings/should_compile/all.T
index 2934db7ad4..3c514245fe 100644
--- a/testsuite/tests/warnings/should_compile/all.T
+++ b/testsuite/tests/warnings/should_compile/all.T
@@ -47,3 +47,5 @@ test('T19564d', normal, compile, [''])
test('T19296', normal, compile, ['-fdiagnostics-show-caret -Wredundant-constraints -dsuppress-uniques'])
test('DodgyExports01', normal, compile, ['-Wdodgy-exports'])
test('DerivingTypeable', normal, compile, ['-Wderiving-typeable'])
+test('T18862a', normal, compile, [''])
+test('T18862b', normal, compile, [''])
diff --git a/utils/check-exact/ExactPrint.hs b/utils/check-exact/ExactPrint.hs
index 3fb283e1ff..2c96ff49ea 100644
--- a/utils/check-exact/ExactPrint.hs
+++ b/utils/check-exact/ExactPrint.hs
@@ -11,6 +11,7 @@
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-} -- For the (StmtLR GhcPs GhcPs (LocatedA (body GhcPs))) ExactPrint instance
module ExactPrint
diff --git a/utils/haddock b/utils/haddock
-Subproject e057bfc880d98fe872e3ee9291d2ee1cd3ceecc
+Subproject b02188ab1cc46dd82395a22b04f890cf15f3fea