summaryrefslogtreecommitdiff
path: root/compiler/GHC/HsToCore
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/HsToCore')
-rw-r--r--compiler/GHC/HsToCore/Pmc/Solver.hs51
1 files changed, 45 insertions, 6 deletions
diff --git a/compiler/GHC/HsToCore/Pmc/Solver.hs b/compiler/GHC/HsToCore/Pmc/Solver.hs
index b493d41889..9337a9e7cf 100644
--- a/compiler/GHC/HsToCore/Pmc/Solver.hs
+++ b/compiler/GHC/HsToCore/Pmc/Solver.hs
@@ -868,15 +868,23 @@ addCoreCt nabla x e = do
-- Otherwise we alternate endlessly between [] and ""
[] -> data_con_app x emptyInScopeSet nilDataCon []
s' -> core_expr x (mkListExpr charTy (map mkCharExpr s'))
+
| Just lit <- coreExprAsPmLit e
= pm_lit x lit
+
| Just (in_scope, _empty_floats@[], dc, _arg_tys, args)
<- exprIsConApp_maybe in_scope_env e
= data_con_app x in_scope dc args
- -- See Note [Detecting pattern synonym applications in expressions]
- | Var y <- e, Nothing <- isDataConId_maybe x
- -- We don't consider DataCons flexible variables
+ -- See Note [Detecting pattern synonym applications in expressions]
+
+ | (Var y, args) <- collectArgs e
+ -- This catches the case of a variable constraints `x ~ y`
+ , all isTypeArg args
+ -- See Note [Identify VarInfo modulo type arguments]
+ , Nothing <- isDataConId_maybe x
+ -- We don't consider DataCons flexible variables
= modifyT (\nabla -> addVarCt nabla x y)
+
| otherwise
-- Any other expression. Try to find other uses of a semantically
-- equivalent expression and represent them by the same variable!
@@ -1059,10 +1067,41 @@ In the end, replacing dictionaries with an error value in the pattern-match
checker was the most self-contained, although we might want to revisit once
we implement a more robust approach to computing equality in the pattern-match
checker (see #19272).
--}
-{- Note [The Pos/Neg invariant]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Note [Identify VarInfo modulo type arguments]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider (#23145)
+
+ f :: (forall a. Maybe a) -> Maybe b
+ f (Just x) = Just x
+ f Nothing = Nothing
+
+this desugars to
+
+ f = \ @b (ds :: forall a. Maybe a) ->
+ case ds @b of {
+ Just x -> Just @b x;
+ Nothing ->
+ case ds @Any of {
+ Just ipv -> patError ...
+ Nothing -> Nothing @b
+ }
+ }
+
+Note we match on `ds` twice with different type arguments applied, but since the
+type arguments are erased both matches must yield the same value. Hence we should
+not warn about `f` having an incomplete match.
+A good way to achieve that is discard the type arguments in the constraint `pm
+~ ds @b` (where `pm` is the match variable of the outermost Case) so that we
+get `pm ~ ds`, with the outcome of giving both match variables the same VarInfo
+as `ds`. Long distance information will sort out the rest and we the checker
+detects `f` as exhaustive.
+
+Note that the potential type confusion is harmless as the TyCon of `ds` and `pm`
+must be the same (if it exists).
+
+Note [The Pos/Neg invariant]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Invariant applying to each VarInfo: Whenever we have @C @tvs args@ in 'vi_pos',
any entry in 'vi_neg' must be incomparable to C (return Nothing) according to
'eqPmAltCons'. Those entries that are comparable either lead to a refutation