diff --git a/compiler/parser/RdrHsSyn.hs b/compiler/parser/RdrHsSyn.hs
index 5784b9ecdb553cb054bef3d24201853d233744c8..e4f74d6b735b2b05eedf72f5018e1f2a97471a17 100644
--- a/compiler/parser/RdrHsSyn.hs
+++ b/compiler/parser/RdrHsSyn.hs
@@ -25,6 +25,7 @@ module   RdrHsSyn (
         mkTyClD, mkInstD,
         mkRdrRecordCon, mkRdrRecordUpd,
         setRdrNameSpace,
+        filterCTuple,
 
         cvBindGroup,
         cvBindsAndSigs,
@@ -91,7 +92,8 @@ import Lexeme           ( isLexCon )
 import Type             ( TyThing(..) )
 import TysWiredIn       ( cTupleTyConName, tupleTyCon, tupleDataCon,
                           nilDataConName, nilDataConKey,
-                          listTyConName, listTyConKey, eqTyCon_RDR )
+                          listTyConName, listTyConKey, eqTyCon_RDR,
+                          tupleTyConName, cTupleTyConNameArity_maybe )
 import ForeignCall
 import PrelNames        ( forall_tv_RDR, allNameStrings )
 import SrcLoc
@@ -765,6 +767,13 @@ data_con_ty_con dc
   | otherwise  -- See Note [setRdrNameSpace for wired-in names]
   = Unqual (setOccNameSpace tcClsName (getOccName dc))
 
+-- | Replaces constraint tuple names with corresponding boxed ones.
+filterCTuple :: RdrName -> RdrName
+filterCTuple (Exact n)
+  | Just arity <- cTupleTyConNameArity_maybe n
+  = Exact $ tupleTyConName BoxedTuple arity
+filterCTuple rdr = rdr
+
 
 {- Note [setRdrNameSpace for wired-in names]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -809,12 +818,19 @@ checkTyVars pp_what equals_or_where tc tparms
     chk t@(L loc _)
         = Left (loc,
                 vcat [ text "Unexpected type" <+> quotes (ppr t)
-                     , text "In the" <+> pp_what <+> ptext (sLit "declaration for") <+> quotes (ppr tc)
+                     , text "In the" <+> pp_what <+> ptext (sLit "declaration for") <+> quotes tc'
                      , vcat[ (text "A" <+> pp_what <+> ptext (sLit "declaration should have form"))
-                     , nest 2 (pp_what <+> ppr tc
+                     , nest 2 (pp_what <+> tc'
                                        <+> hsep (map text (takeList tparms allNameStrings))
                                        <+> equals_or_where) ] ])
 
+    -- Avoid printing a constraint tuple in the error message. Print
+    -- a plain old tuple instead (since that's what the user probably
+    -- wrote). See #14907
+    tc' = ppr $ fmap filterCTuple tc
+
+
+
 whereDots, equalsDots :: SDoc
 -- Second argument to checkTyVars
 whereDots  = text "where ..."
diff --git a/compiler/prelude/TysWiredIn.hs b/compiler/prelude/TysWiredIn.hs
index 1d47185f022c928724264bc9b51694187bd5d070..6e64d73d3458ded93d7b4689d3c26bc77e8ecd78 100644
--- a/compiler/prelude/TysWiredIn.hs
+++ b/compiler/prelude/TysWiredIn.hs
@@ -80,6 +80,7 @@ module TysWiredIn (
 
         -- ** Constraint tuples
         cTupleTyConName, cTupleTyConNames, isCTupleTyConName,
+        cTupleTyConNameArity_maybe,
         cTupleDataConName, cTupleDataConNames,
 
         -- * Any
@@ -160,6 +161,8 @@ import BooleanFormula   ( mkAnd )
 
 import qualified Data.ByteString.Char8 as BS
 
+import Data.List        ( elemIndex )
+
 alpha_tyvar :: [TyVar]
 alpha_tyvar = [alphaTyVar]
 
@@ -777,6 +780,17 @@ isCTupleTyConName n
    nameModule n == gHC_CLASSES
    && n `elemNameSet` cTupleTyConNameSet
 
+-- | If the given name is that of a constraint tuple, return its arity.
+-- Note that this is inefficient.
+cTupleTyConNameArity_maybe :: Name -> Maybe Arity
+cTupleTyConNameArity_maybe n
+  | not (isCTupleTyConName n) = Nothing
+  | otherwise = fmap adjustArity (n `elemIndex` cTupleTyConNames)
+  where
+    -- Since `cTupleTyConNames` jumps straight from the `0` to the `2`
+    -- case, we have to adjust accordingly our calculated arity.
+    adjustArity a = if a > 0 then a + 1 else a
+
 cTupleDataConName :: Arity -> Name
 cTupleDataConName arity
   = mkExternalName (mkCTupleDataConUnique arity) gHC_CLASSES
diff --git a/compiler/rename/RnEnv.hs b/compiler/rename/RnEnv.hs
index 16897c26814a6f9a4e1ea6300e037734c4f39c3b..516c43c14a1ebc3fb6433180a4077c93faef6eae 100644
--- a/compiler/rename/RnEnv.hs
+++ b/compiler/rename/RnEnv.hs
@@ -53,7 +53,7 @@ import RdrName
 import HscTypes
 import TcEnv
 import TcRnMonad
-import RdrHsSyn         ( setRdrNameSpace )
+import RdrHsSyn         ( filterCTuple, setRdrNameSpace )
 import TysWiredIn
 import Name
 import NameSet
@@ -1653,4 +1653,4 @@ badOrigBinding name
     --
     -- (See Trac #13968.)
   where
-    occ = rdrNameOcc name
+    occ = rdrNameOcc $ filterCTuple name
diff --git a/testsuite/tests/rename/should_fail/T14907a.hs b/testsuite/tests/rename/should_fail/T14907a.hs
new file mode 100644
index 0000000000000000000000000000000000000000..d68e706b1682509df8f7ec4b93cd19de73abef10
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T14907a.hs
@@ -0,0 +1,3 @@
+module T14907a where
+
+class (Bool, a, b)
diff --git a/testsuite/tests/rename/should_fail/T14907a.stderr b/testsuite/tests/rename/should_fail/T14907a.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..26ce914c3dbc0dd76322839930820c51f0dcd28e
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T14907a.stderr
@@ -0,0 +1,6 @@
+
+T14907a.hs:3:8: error:
+    Unexpected type ‘Bool’
+    In the class declaration for ‘(,,)’
+    A class declaration should have form
+      class (,,) a b c where ...
diff --git a/testsuite/tests/rename/should_fail/T14907b.hs b/testsuite/tests/rename/should_fail/T14907b.hs
new file mode 100644
index 0000000000000000000000000000000000000000..4cd4f282e48068e3aae29a6a7a0af2c865b7181c
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T14907b.hs
@@ -0,0 +1,7 @@
+module T14907b where
+
+-- This is effectively trying to redefine the constraint tuples already
+-- defined in 'GHC.Classes'.
+class ()
+class (a,b)
+class (a,b,c)
diff --git a/testsuite/tests/rename/should_fail/T14907b.stderr b/testsuite/tests/rename/should_fail/T14907b.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..b76cc11e2a7d6e602751da9e98cdff86e5332a05
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T14907b.stderr
@@ -0,0 +1,6 @@
+
+T14907b.hs:5:1: error: Illegal binding of built-in syntax: ()
+
+T14907b.hs:6:1: error: Illegal binding of built-in syntax: (,)
+
+T14907b.hs:7: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 182dc421fbc2c981fd621c569455dea5b669e59b..db0db47ca9ed32f3adc4df678553a2d71c6d145a 100644
--- a/testsuite/tests/rename/should_fail/all.T
+++ b/testsuite/tests/rename/should_fail/all.T
@@ -131,6 +131,8 @@ test('T13947', normal, compile_fail, [''])
 test('T13847', normal, multimod_compile_fail, ['T13847','-v0'])
 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'])