diff options
author | sheaf <sam.derbyshire@gmail.com> | 2022-03-11 17:01:33 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-03-14 15:08:24 -0400 |
commit | 8eadea670adb5de49ddba7e23d04ec8242ba76a3 (patch) | |
tree | 11d5284281b78446cbbe6dce54bc275b3bad3fba /compiler/GHC/Tc/Errors/Ppr.hs | |
parent | 106413f094d01485503a9b84fa4545d938ea934d (diff) | |
download | haskell-8eadea670adb5de49ddba7e23d04ec8242ba76a3.tar.gz |
Fix isLiftedType_maybe and handle fallout
As #20837 pointed out, `isLiftedType_maybe` returned `Just False` in
many situations where it should return `Nothing`, because it didn't
take into account type families or type variables.
In this patch, we fix this issue. We rename `isLiftedType_maybe` to
`typeLevity_maybe`, which now returns a `Levity` instead of a boolean.
We now return `Nothing` for types with kinds of the form
`TYPE (F a1 ... an)` for a type family `F`, as well as
`TYPE (BoxedRep l)` where `l` is a type variable.
This fix caused several other problems, as other parts of the compiler
were relying on `isLiftedType_maybe` returning a `Just` value, and were
now panicking after the above fix. There were two main situations in
which panics occurred:
1. Issues involving the let/app invariant. To uphold that invariant,
we need to know whether something is lifted or not. If we get an
answer of `Nothing` from `isLiftedType_maybe`, then we don't know
what to do. As this invariant isn't particularly invariant, we
can change the affected functions to not panic, e.g. by behaving
the same in the `Just False` case and in the `Nothing` case
(meaning: no observable change in behaviour compared to before).
2. Typechecking of data (/newtype) constructor patterns. Some programs
involving patterns with unknown representations were accepted, such
as T20363. Now that we are stricter, this caused further issues,
culminating in Core Lint errors. However, the behaviour was
incorrect the whole time; the incorrectness only being revealed by
this change, not triggered by it.
This patch fixes this by overhauling where the representation
polymorphism involving pattern matching are done. Instead of doing
it in `tcMatches`, we instead ensure that the `matchExpected`
functions such as `matchExpectedFunTys`, `matchActualFunTySigma`,
`matchActualFunTysRho` allow return argument pattern types which
have a fixed RuntimeRep (as defined in Note [Fixed RuntimeRep]).
This ensures that the pattern matching code only ever handles types
with a known runtime representation. One exception was that
patterns with an unknown representation type could sneak in via
`tcConPat`, which points to a missing representation-polymorphism
check, which this patch now adds.
This means that we now reject the program in #20363, at least until
we implement PHASE 2 of FixedRuntimeRep (allowing type families in
RuntimeRep positions). The aforementioned refactoring, in which
checks have been moved to `matchExpected` functions, is a first
step in implementing PHASE 2 for patterns.
Fixes #20837
Diffstat (limited to 'compiler/GHC/Tc/Errors/Ppr.hs')
-rw-r--r-- | compiler/GHC/Tc/Errors/Ppr.hs | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs index f6e71f57cf..ad78cfaf76 100644 --- a/compiler/GHC/Tc/Errors/Ppr.hs +++ b/compiler/GHC/Tc/Errors/Ppr.hs @@ -1741,8 +1741,43 @@ pprTcSolverReportMsg _ (FixedRuntimeRepError frr_infos) = (if length frr_infos > 1 then (bullet <+>) else id) $ vcat [ sep [ pprFRROrigin frr_orig , text "does not have a fixed runtime representation." ] - , text "Its type is:" - , nest 2 $ ppr ty <+> dcolon <+> pprWithTYPE (typeKind ty) ] + , type_printout ty ] + + -- Don't print out the type (only the kind), if the type includes + -- a confusing cast, unless the user passed -fprint-explicit-coercions. + -- + -- Example: + -- + -- In T20363, we have a representation-polymorphism error with a type + -- of the form + -- + -- ( (# #) |> co ) :: TYPE NilRep + -- + -- where NilRep is a nullary type family application which reduces to TupleRep '[]. + -- We prefer avoiding showing the cast to the user, but we also don't want to + -- print the confusing: + -- + -- (# #) :: TYPE NilRep + -- + -- So in this case we simply don't print the type, only the kind. + confusing_cast :: Type -> Bool + confusing_cast ty = + case ty of + CastTy inner_ty _ + -- A confusing cast is one that is responsible + -- for a representation-polymorphism error. + -> isConcrete (typeKind inner_ty) + _ -> False + + type_printout :: Type -> SDoc + type_printout ty = + sdocOption sdocPrintExplicitCoercions $ \ show_coercions -> + if confusing_cast ty && not show_coercions + then vcat [ text "Its kind is:" + , nest 2 $ pprWithTYPE (typeKind ty) + , text "(Use -fprint-explicit-coercions to see the full type.)" ] + else vcat [ text "Its type is:" + , nest 2 $ ppr ty <+> dcolon <+> pprWithTYPE (typeKind ty) ] -- In PHASE 1 of FixedRuntimeRep, we don't allow rewriting in hasFixedRuntimeRep, -- so we add a special message to explain this to the user. |