clash-lang / ghc-typelits-natnormalise

Normalise GHC.TypeLits.Nat equations
Other
43 stars 15 forks source link

Soundness issue with inequalities and subtraction. #58

Open soundlogic2236 opened 3 years ago

soundlogic2236 commented 3 years ago

While #34 appears to be fixed, another issue around inequalities and subtraction occurs. The following invalid inference rule is accepted:

invalid :: forall x y n. (x - n <=? y - n) :~: 'True -> (x <=? y) :~: 'True
invalid Refl = Refl

As demonstrated below, this is unsound:

absurdity :: 'True :~: 'False
absurdity = makeProof @5 @0 (allLe @5 @0) Refl where
    makeProof :: forall x y. (x <=? y) :~: 'True -> (x <=? y) :~: 'False -> 'True :~: 'False
    makeProof = worker where
        worker :: forall a' b'. (x <=? y) :~: a' -> (x <=? y) :~: b' -> a' :~: b'
        worker Refl Refl = Refl
    allLe :: forall x y. (x <=? y) :~: 'True
    allLe = worker where
        worker :: (x <=? y) :~: 'True
        worker = invalid @x @y @x worker'
        worker' :: (x - x <=? y - x) :~: 'True
        worker' = worker'' @(x - x) @(y - x) Refl
        worker'' :: forall n m. n :~: 0 -> (n <=? m) :~: 'True
        worker'' Refl = Refl

The fundamental problem is that the subtraction may reduce the left hand side to zero, and the rule forall x. 0 <= x then triggers even if x itself can't reduce, resulting in assertions like 0 <= 2 - 5 which should never be turned into 5 <= 2.

christiaanb commented 3 years ago

Ugh, I “hate” that subtraction was ever added to GHC.TypeLits… Thanks for the report though! I’ll have a think whether the plugin should either require n <= x and n <= y or some other preconditions to make the inference valid.