summaryrefslogtreecommitdiff
path: root/compiler/coreSyn/CoreSyn.hs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2018-09-13 11:23:53 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2018-09-13 11:35:00 +0100
commitbd76875ae6ad0cdd734564dddfb9ab88a6de9579 (patch)
treedddaeaf707a06f3e4b34d462978a20f89c12b0f6 /compiler/coreSyn/CoreSyn.hs
parent291b0f89703f28631a381549e1838aa06195d011 (diff)
downloadhaskell-bd76875ae6ad0cdd734564dddfb9ab88a6de9579.tar.gz
Allow (~) in the head of a quantified constraints
Since the introduction of quantified constraints, GHC has rejected a quantified constraint with (~) in the head, thus f :: (forall a. blah => a ~ ty) => stuff I am frankly dubious that this is ever useful. But /is/ necessary for Coercible (representation equality version of (~)) and it does no harm to allow it for (~) as well. Plus, our users are asking for it (Trac #15359, #15625). It was really only excluded by accident, so this patch lifts the restriction. See TcCanonical Note [Equality superclasses in quantified constraints] There are a number of wrinkles: * If the context of the quantified constraint is empty, we can get trouble when we get down to unboxed equality (a ~# b) or (a ~R# b), as Trac #15625 showed. This is even more of a corner case, but it produced an outright crash, so I elaborated the superclass machinery in TcCanonical.makeStrictSuperClasses to add a void argument in this case. See Note [Equality superclasses in quantified constraints] * The restriction on (~) was in TcValidity.checkValidInstHead. In lifting the restriction I discovered an old special case for (~), namely | clas_nm `elem` [ heqTyConName, eqTyConName] , nameModule clas_nm /= this_mod This was (solely) to support the strange instance instance a ~~ b => a ~ b in Data.Type.Equality. But happily that is no longer with us, since commit f265008fb6f70830e7e92ce563f6d83833cef071 Refactor (~) to reduce the suerpclass stack So I removed the special case. * I found that the Core invariants on when we could have co = <expr> were entirely not written down. (Getting this wrong ws the proximate source of the crash in Trac #15625. So - Documented them better in CoreSyn Note [CoreSyn type and coercion invariant], - Modified CoreOpt and CoreLint to match - Modified CoreUtils.bindNonRec to match - Made MkCore.mkCoreLet use bindNonRec, rather than duplicate its logic - Made Simplify.rebuildCase case-to-let respect Note [CoreSyn type and coercion invariant],
Diffstat (limited to 'compiler/coreSyn/CoreSyn.hs')
-rw-r--r--compiler/coreSyn/CoreSyn.hs71
1 files changed, 46 insertions, 25 deletions
diff --git a/compiler/coreSyn/CoreSyn.hs b/compiler/coreSyn/CoreSyn.hs
index 025c19e3ca..aa27d7a7fb 100644
--- a/compiler/coreSyn/CoreSyn.hs
+++ b/compiler/coreSyn/CoreSyn.hs
@@ -46,7 +46,7 @@ module CoreSyn (
exprToType, exprToCoercion_maybe,
applyTypeToArg,
- isValArg, isTypeArg, isTyCoArg, valArgCount, valBndrCount,
+ isValArg, isTypeArg, isCoArg, isTyCoArg, valArgCount, valBndrCount,
isRuntimeArg, isRuntimeVar,
-- * Tick-related functions
@@ -173,6 +173,7 @@ These data types are the heart of the compiler
-- The language consists of the following elements:
--
-- * Variables
+-- See Note [Variable occurrences in Core]
--
-- * Primitive literals
--
@@ -187,29 +188,10 @@ These data types are the heart of the compiler
-- this corresponds to allocating a thunk for the things
-- bound and then executing the sub-expression.
--
--- #top_level_invariant#
--- #letrec_invariant#
---
--- The right hand sides of all top-level and recursive @let@s
--- /must/ be of lifted type (see "Type#type_classification" for
--- the meaning of /lifted/ vs. /unlifted/). There is one exception
--- to this rule, top-level @let@s are allowed to bind primitive
--- string literals, see Note [CoreSyn top-level string literals].
---
+-- See Note [CoreSyn letrec invariant]
-- See Note [CoreSyn let/app invariant]
-- See Note [Levity polymorphism invariants]
---
--- #type_let#
--- We allow a /non-recursive/ let to bind a type variable, thus:
---
--- > Let (NonRec tv (Type ty)) body
---
--- This can be very convenient for postponing type substitutions until
--- the next run of the simplifier.
---
--- At the moment, the rest of the compiler only deals with type-let
--- in a Let expression, rather than at top level. We may want to revist
--- this choice.
+-- See Note [CoreSyn type and coercion invariant]
--
-- * Case expression. Operationally this corresponds to evaluating
-- the scrutinee (expression examined) to weak head normal form
@@ -371,13 +353,25 @@ PrelRules for the rationale for this restriction.
-------------------------- CoreSyn INVARIANTS ---------------------------
-Note [CoreSyn top-level invariant]
+Note [Variable occurrences in Core]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-See #toplevel_invariant#
+Variable /occurrences/ are never CoVars, though /bindings/ can be.
+All CoVars appear in Coercions.
+
+For example
+ \(c :: Age~#Int) (d::Int). d |> (sym c)
+Here 'c' is a CoVar, which is lambda-bound, but it /occurs/ in
+a Coercion, (sym c).
Note [CoreSyn letrec invariant]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-See #letrec_invariant#
+The right hand sides of all top-level and recursive @let@s
+/must/ be of lifted type (see "Type#type_classification" for
+the meaning of /lifted/ vs. /unlifted/).
+
+There is one exception to this rule, top-level @let@s are
+allowed to bind primitive string literals: see
+Note [CoreSyn top-level string literals].
Note [CoreSyn top-level string literals]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -451,6 +445,27 @@ which will generate a @case@ if necessary
The let/app invariant is initially enforced by mkCoreLet and mkCoreApp in
coreSyn/MkCore.
+Note [CoreSyn type and coercion invariant]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We allow a /non-recursive/, /non-top-level/ let to bind type and
+coercion variables. These can be very convenient for postponing type
+substitutions until the next run of the simplifier.
+
+* A type variable binding must have a RHS of (Type ty)
+
+* A coercion variable binding must have a RHS of (Coercion co)
+
+ It is possible to have terms that return a coercion, but we use
+ case-binding for those; e.g.
+ case (eq_sel d) of (co :: a ~# b) -> blah
+ where eq_sel :: (a~b) -> (a~#b)
+
+ Or even even
+ case (df @Int) of (co :: a ~# b) -> blah
+ Which is very exotic, and I think never encountered; but see
+ Note [Equality superclasses in quantified constraints]
+ in TcCanonical
+
Note [CoreSyn case invariants]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See #case_invariants#
@@ -2102,6 +2117,12 @@ isTyCoArg (Type {}) = True
isTyCoArg (Coercion {}) = True
isTyCoArg _ = False
+-- | Returns @True@ iff the expression is a 'Coercion'
+-- expression at its top level
+isCoArg :: Expr b -> Bool
+isCoArg (Coercion {}) = True
+isCoArg _ = False
+
-- | Returns @True@ iff the expression is a 'Type' expression at its
-- top level. Note this does NOT include 'Coercion's.
isTypeArg :: Expr b -> Bool