diff --git a/compiler/typecheck/TcCanonical.lhs b/compiler/typecheck/TcCanonical.lhs
index 6cd77b1c07ab72b79ac516828c9af63cc640da4a..f11c9d9ed92feef16ef14f959558ab8959a71cfb 100644
--- a/compiler/typecheck/TcCanonical.lhs
+++ b/compiler/typecheck/TcCanonical.lhs
@@ -492,13 +492,21 @@ flatten f ctxt (FunTy ty1 ty2)
        ; return (mkFunTy xi1 xi2, mkTcFunCo Nominal co1 co2) }
 
 flatten f ctxt (TyConApp tc tys)
+
+  -- Expand type synonyms that mention type families 
+  -- on the RHS; see Note [Flattening synonyms]
+  | Just (tenv, rhs, tys') <- tcExpandTyCon_maybe tc tys
+  , any isSynFamilyTyCon (tyConsOfType rhs)
+  = flatten f ctxt (mkAppTys (substTy (mkTopTvSubst tenv) rhs) tys')
+
   -- For * a normal data type application
-  --     * type synonym application  See Note [Flattening synonyms]
   --     * data family application
+  --     * type synonym application whose RHS does not mention type families
+  --             See Note [Flattening synonyms]
   -- we just recursively flatten the arguments.
   | not (isSynFamilyTyCon tc)
-    = do { (xis,cos) <- flattenMany f ctxt tys
-         ; return (mkTyConApp tc xis, mkTcTyConAppCo Nominal tc cos) }
+  = do { (xis,cos) <- flattenMany f ctxt tys
+       ; return (mkTyConApp tc xis, mkTcTyConAppCo Nominal tc cos) }
 
   -- Otherwise, it's a type function application, and we have to
   -- flatten it away as well, and generate a new given equality constraint
@@ -534,6 +542,9 @@ flatten _f ctxt ty@(ForAllTy {})
 
 Note [Flattening synonyms]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+Not expanding synonyms aggressively improves error messages, and
+keeps types smaller. But we need to take care.
+
 Suppose
    type T a = a -> a
 and we want to flatten the type (T (F a)).  Then we can safely flatten
@@ -541,12 +552,16 @@ the (F a) to a skolem, and return (T fsk).  We don't need to expand the
 synonym.  This works because TcTyConAppCo can deal with synonyms
 (unlike TyConAppCo), see Note [TcCoercions] in TcEvidence.
 
-Not expanding synonyms aggressively improves error messages.
+But (Trac #8979) for
+   type T a = (F a, a)    where F is a type function
+we must expand the synonym in (say) T Int, to expose the type functoin
+to the flattener.
+
 
 Note [Flattening under a forall]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Under a forall, we
-  (a) MUST apply the inert subsitution
+  (a) MUST apply the inert substitution
   (b) MUST NOT flatten type family applications
 Hence FMSubstOnly.
 
diff --git a/testsuite/tests/indexed-types/should_compile/T8978.hs b/testsuite/tests/indexed-types/should_compile/T8978.hs
new file mode 100644
index 0000000000000000000000000000000000000000..077a07db311ba97336da0cc23bae2502a8d42597
--- /dev/null
+++ b/testsuite/tests/indexed-types/should_compile/T8978.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
+module T8978 where
+
+type Syn a = Associated a
+
+class Eq (Associated a) => Foo a where
+    type Associated a :: *
+    foo :: a -> Syn a -> Bool
+
+instance Foo () where
+    type Associated () = Int
+    foo _ x = x == x
diff --git a/testsuite/tests/indexed-types/should_compile/T8979.hs b/testsuite/tests/indexed-types/should_compile/T8979.hs
new file mode 100644
index 0000000000000000000000000000000000000000..85e13cee4e08ad07eeaf5a7bb67d344722b9380e
--- /dev/null
+++ b/testsuite/tests/indexed-types/should_compile/T8979.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE TypeFamilies #-}
+module T8979 where
+
+type family F a
+type family G a
+
+type H a = G a
+
+f :: F (G Char) -> F (H Char)
+f a = a
diff --git a/testsuite/tests/indexed-types/should_compile/all.T b/testsuite/tests/indexed-types/should_compile/all.T
index 76682ad356cf2ca59f13122c10df865f8f5dcb7c..5f304463c627be6d853e600f9a1927cd72f08312 100644
--- a/testsuite/tests/indexed-types/should_compile/all.T
+++ b/testsuite/tests/indexed-types/should_compile/all.T
@@ -241,3 +241,5 @@ test('ClosedFam2', extra_clean(['ClosedFam2.o-boot', 'ClosedFam2.hi-boot']),
 test('T8651', normal, compile, [''])
 test('T8889', normal, compile, [''])
 test('T8913', normal, compile, [''])
+test('T8978', normal, compile, [''])
+test('T8979', normal, compile, [''])
diff --git a/testsuite/tests/indexed-types/should_fail/T5439.stderr b/testsuite/tests/indexed-types/should_fail/T5439.stderr
index d5f031898565a7db0c274840de66859f81b1b5f2..18af3fa7cf698fe60bfa49268c4e70e558025b63 100644
--- a/testsuite/tests/indexed-types/should_fail/T5439.stderr
+++ b/testsuite/tests/indexed-types/should_fail/T5439.stderr
@@ -1,25 +1,26 @@
-
-T5439.hs:83:28:
-    Couldn't match type ‘Attempt (HNth n0 l0) -> Attempt (HElemOf l0)’
-                  with ‘Attempt (WaitOpResult (WaitOps rs))’
-    Expected type: f (Attempt (HNth n0 l0) -> Attempt (HElemOf l0))
-      Actual type: f (Attempt (WaitOpResult (WaitOps rs)))
-    Relevant bindings include
-      register :: Bool -> Peano n -> WaitOps (HDrop n rs) -> IO Bool
-        (bound at T5439.hs:65:9)
-      ev :: f (Attempt (WaitOpResult (WaitOps rs)))
-        (bound at T5439.hs:62:22)
-      ops :: WaitOps rs (bound at T5439.hs:62:18)
-      registerWaitOp :: WaitOps rs
-                        -> f (Attempt (WaitOpResult (WaitOps rs))) -> IO Bool
-        (bound at T5439.hs:62:3)
-    In the first argument of ‘complete’, namely ‘ev’
-    In the expression: complete ev
-
-T5439.hs:83:39:
-    Couldn't match expected type ‘Peano n0’
-                with actual type ‘Attempt α0’
-    In the second argument of ‘($)’, namely
-      ‘Failure (e :: SomeException)’
-    In the second argument of ‘($)’, namely
-      ‘inj $ Failure (e :: SomeException)’
+
+T5439.hs:83:28:
+    Couldn't match type ‘Attempt (HHead (HDrop n0 l0))
+                         -> Attempt (HElemOf l0)’
+                  with ‘Attempt (WaitOpResult (WaitOps rs))’
+    Expected type: f (Attempt (HNth n0 l0) -> Attempt (HElemOf l0))
+      Actual type: f (Attempt (WaitOpResult (WaitOps rs)))
+    Relevant bindings include
+      register :: Bool -> Peano n -> WaitOps (HDrop n rs) -> IO Bool
+        (bound at T5439.hs:65:9)
+      ev :: f (Attempt (WaitOpResult (WaitOps rs)))
+        (bound at T5439.hs:62:22)
+      ops :: WaitOps rs (bound at T5439.hs:62:18)
+      registerWaitOp :: WaitOps rs
+                        -> f (Attempt (WaitOpResult (WaitOps rs))) -> IO Bool
+        (bound at T5439.hs:62:3)
+    In the first argument of ‘complete’, namely ‘ev’
+    In the expression: complete ev
+
+T5439.hs:83:39:
+    Couldn't match expected type ‘Peano n0’
+                with actual type ‘Attempt α0’
+    In the second argument of ‘($)’, namely
+      ‘Failure (e :: SomeException)’
+    In the second argument of ‘($)’, namely
+      ‘inj $ Failure (e :: SomeException)’
diff --git a/testsuite/tests/indexed-types/should_fail/T5934.stderr b/testsuite/tests/indexed-types/should_fail/T5934.stderr
index cf7bf8784eea0851ba520954410ad348a76aa698..85ab1a1804e37f83e210f9a6cdb9bf6fcad66ccb 100644
--- a/testsuite/tests/indexed-types/should_fail/T5934.stderr
+++ b/testsuite/tests/indexed-types/should_fail/T5934.stderr
@@ -1,7 +1,8 @@
-
-T5934.hs:12:7:
-    Cannot instantiate unification variable ‘a0’
-    with a type involving foralls: (forall s. GenST s) -> Int
-      Perhaps you want ImpredicativeTypes
-    In the expression: 0
-    In an equation for ‘run’: run = 0
+
+T5934.hs:12:7:
+    Cannot instantiate unification variable ‘a0’
+    with a type involving foralls:
+      (forall s. Gen (PrimState (ST s))) -> Int
+      Perhaps you want ImpredicativeTypes
+    In the expression: 0
+    In an equation for ‘run’: run = 0