stgEqType :: Type -> Type -> Bool
-- Compare types, but crudely because we have discarded
-- both casts and type applications, so types might look
-- different but be the same.  So reply "True" if in doubt.
-- "False" means that the types are definitely different.
--
-- Fundamentally this is a losing battle because of unsafeCoerce

stgEqType orig_ty1 orig_ty2
  = gos (repType orig_ty1) (repType orig_ty2)
  where
    gos :: RepType -> RepType -> Bool
    gos (UbxTupleRep tys1) (UbxTupleRep tys2)
      = equalLength tys1 tys2 && and (zipWith go tys1 tys2)
    gos (UnaryRep ty1) (UnaryRep ty2) = go ty1 ty2
    gos _ _ = False

    go :: UnaryType -> UnaryType -> Bool
    go ty1 ty2
      | Just (tc1, tc_args1) <- splitTyConApp_maybe ty1
      , Just (tc2, tc_args2) <- splitTyConApp_maybe ty2
      , let res = if tc1 == tc2
                  then equalLength tc_args1 tc_args2 && and (zipWith (gos `on` repType) tc_args1 tc_args2)
                  else  -- TyCons don't match; but don't bleat if either is a
                        -- family TyCon because a coercion might have made it
                        -- equal to something else
                    (isFamilyTyCon tc1 || isFamilyTyCon tc2)
      = if res then True
        else
        pprTrace "stgEqType: unequal" (vcat [ppr ty1, ppr ty2])
        False

      | otherwise = True  -- Conservatively say "fine".
                          -- Type variables in particular
stgEqType :: Type -> Type -> Bool
stgEqType orig_ty1 orig_ty2
  = gos (repType orig_ty1) (repType orig_ty2)
  where
    gos :: RepType -> RepType -> Bool
    gos (UbxTupleRep tys1) (UbxTupleRep tys2)
      = equalLength tys1 tys2 && and (zipWith go tys1 tys2)
    gos (UnaryRep ty1) (UnaryRep ty2) = go ty1 ty2
    gos _ _ = False

    go :: UnaryType -> UnaryType -> Bool
    go ty1 ty2
      | Just (tc1, tc_args1) <- splitTyConApp_maybe ty1
      , Just (tc2, tc_args2) <- splitTyConApp_maybe ty2
      , let res = if tc1 == tc2
                  then equalLength tc_args1 tc_args2 && and (zipWith (gos `on` repType) tc_args1 tc_args2)
                  else  -- TyCons don't match; but don't bleat if either is a
                        -- family TyCon because a coercion might have made it
                        -- equal to something else
                    (isFamilyTyCon tc1 || isFamilyTyCon tc2)
      = if res then True
        else
        pprTrace "stgEqType: unequal" (vcat [ppr ty1, ppr ty2])
        False

      | otherwise = True  -- Conservatively say "fine".
                          -- Type variables in particular
stgEqType orig_ty1 orig_ty2
  = gos (repType orig_ty1) (repType orig_ty2)
  where
    gos :: RepType -> RepType -> Bool
    gos (UbxTupleRep tys1) (UbxTupleRep tys2)
      = equalLength tys1 tys2 && and (zipWith go tys1 tys2)
    gos (UnaryRep ty1) (UnaryRep ty2) = go ty1 ty2
    gos _ _ = False

    go :: UnaryType -> UnaryType -> Bool
    go ty1 ty2
      | Just (tc1, tc_args1) <- splitTyConApp_maybe ty1
      , Just (tc2, tc_args2) <- splitTyConApp_maybe ty2
      , let res = if tc1 == tc2
                  then equalLength tc_args1 tc_args2 && and (zipWith (gos `on` repType) tc_args1 tc_args2)
                  else  -- TyCons don't match; but don't bleat if either is a
                        -- family TyCon because a coercion might have made it
                        -- equal to something else
                    (isFamilyTyCon tc1 || isFamilyTyCon tc2)
      = if res then True
        else
        pprTrace "stgEqType: unequal" (vcat [ppr ty1, ppr ty2])
        False

      | otherwise = True  -- Conservatively say "fine".
                          -- Type variables in particular