summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Dammers <tdammers@gmail.com>2018-03-31 18:25:15 +0200
committerTobias Dammers <tdammers@gmail.com>2018-04-04 09:45:07 +0200
commitf1e5fef1a75b79ef4189bdf7027e8a7bd456e0ef (patch)
treeb481023024bd3ca96f0f7c20ef15947b292b633c
parent87c547dea0620d92f552275eaa39135bdd4e0423 (diff)
downloadhaskell-f1e5fef1a75b79ef4189bdf7027e8a7bd456e0ef.tar.gz
Clean up & document isReflexiveCo.
-rw-r--r--compiler/types/Coercion.hs54
1 files changed, 35 insertions, 19 deletions
diff --git a/compiler/types/Coercion.hs b/compiler/types/Coercion.hs
index c0532332cf..017646046d 100644
--- a/compiler/types/Coercion.hs
+++ b/compiler/types/Coercion.hs
@@ -58,7 +58,7 @@ module Coercion (
pickLR,
- isReflCo, isReflCo_maybe, isReflexiveCo, isReflexiveCo_maybe,
+ isReflCo, isReflCo_maybe, isReflexiveCo,
isReflCoVar_maybe,
-- ** Coercion variables
@@ -359,37 +359,53 @@ isReflCoVar_maybe cv
| otherwise
= Nothing
--- | Tests if this coercion is obviously reflexive. Guaranteed to work
--- very quickly. Sometimes a coercion can be reflexive, but not obviously
--- so. c.f. 'isReflexiveCo'
+-- | Tests if this coercion is obviously reflexive.
+-- See Note [Checking whether coercions are reflexive].
isReflCo :: Coercion -> Bool
isReflCo (Refl {}) = True
isReflCo _ = False
--- | Returns the type coerced if this coercion is reflexive. Guaranteed
--- to work very quickly. Sometimes a coercion can be reflexive, but not
--- obviously so. c.f. 'isReflexiveCo_maybe'
+-- | Returns the type coerced if this coercion is obviously reflexive.
+-- See Note [Checking whether coercions are reflexive].
isReflCo_maybe :: Coercion -> Maybe (Type, Role)
isReflCo_maybe (Refl r ty) = Just (ty, r)
isReflCo_maybe _ = Nothing
--- | Slowly checks if the coercion is reflexive. Don't call this in a loop,
--- as it walks over the entire coercion.
+-- | Slowly checks if the coercion is reflexive.
+-- See Note [Checking whether coercions are reflexive].
isReflexiveCo :: Coercion -> Bool
isReflexiveCo (Refl {}) = True
isReflexiveCo co = eqType ty1 ty2
where Pair ty1 ty2 = coercionKind co
--- | Extracts the coerced type from a reflexive coercion. This potentially
--- walks over the entire coercion, so avoid doing this in a loop.
-isReflexiveCo_maybe :: Coercion -> Maybe (Type, Role)
-isReflexiveCo_maybe (Refl r ty) = Just (ty, r)
-isReflexiveCo_maybe co
- | ty1 `eqType` ty2
- = Just (ty1, r)
- | otherwise
- = Nothing
- where (Pair ty1 ty2, r) = coercionKindRole co
+{-
+
+Note [Checking whether coercions are reflexive]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes a coercion can be reflexive, but not obviously so; in such cases, a
+conclusive will be very expensive, because it requires walking over the entire
+coercion.
+
+Also, when we determine whether a coercion is reflexive, it is sometimes useful
+to also determine the type coerced and return it from the check, but when we
+don't need it, we can write a more efficient implementation using booleans
+instead of `Maybe`.
+
+Because of this, several flavors of the is-reflexive test exist:
+
+- `isReflCo` performs a very quick test, only checking whether the coercion is
+ obviously reflexive. This test may miss non-obviously reflexive coercions,
+ but it is guaranteed to run very quickly.
+- `isReflCo_maybe` performs the same quick test as `isReflCo`, but also returns
+ the type coerced if it has been found to be obviously reflexive.
+- `isReflexiveCo` performs a full, conclusive test; this will correctly detect
+ non-obviously reflexive coercions, but may run slowly.
+
+Previously, `isReflexiveCo_maybe` also existed, but we don't need a full test
+that also returns the type coerced anywhere.
+
+-}
{-
%************************************************************************