@@ -10,6 +10,7 @@ import Idris.Core.TT
1010import Control.Monad.State
1111import Data.Maybe
1212import Data.List hiding (partition)
13+import qualified Data.List(partition)
1314import Debug.Trace
1415
1516data CaseDef = CaseDef [Name] !SC [Term]
@@ -417,8 +418,15 @@ order :: [(Name, Bool)] -> [Clause] -> ([Name], [Clause])
417418order [] cs = ([], cs)
418419order ns' [] = (map fst ns', [])
419420order ns' cs = let patnames = transpose (map (zip ns') (map fst cs))
421+ -- only sort the arguments where there is no clash in
422+ -- constructor tags between families, and no constructor/constant
423+ -- clash, because otherwise we can't reliable make the
424+ -- case distinction on evaluation
425+ (patnames_ord, patnames_rest)
426+ = Data.List.partition (noClash . map snd) patnames
420427 -- note: sortBy . reverse is not nonsense because sortBy is stable
421− pats' = transpose (sortBy moreDistinct (reverse patnames)) in
428+ pats' = transpose (sortBy moreDistinct (reverse patnames_ord)
429+ ++ patnames_rest) in
422430 (getNOrder pats', zipWith rebuild pats' cs)
423431 where
424432 getNOrder [] = error $ "Failed order on " ++ show (map fst ns', cs)
@@ -426,6 +434,16 @@ order ns' cs = let patnames = transpose (map (zip ns') (map fst cs))
426434
427435 rebuild patnames clause = (map snd patnames, snd clause)
428436
437+ noClash [] = True
438+ noClash (p : ps) = not (any (clashPat p) ps) && noClash ps
439+
440+ clashPat (PCon _ _ _) (PConst _) = True
441+ clashPat (PConst _) (PCon _ _ _) = True
442+ clashPat (PCon _ _ _) (PSuc _) = True
443+ clashPat (PSuc _) (PCon _ _ _) = True
444+ clashPat (PCon n i _) (PCon n' i' _) | i == i' = n /= n'
445+ clashPat _ _ = False
446+
429447 -- this compares (+isInaccessible, -numberOfCases)
430448 moreDistinct xs ys = compare (snd . fst . head $ xs, numNames [] (map snd ys))
431449 (snd . fst . head $ ys, numNames [] (map snd xs))