summaryrefslogtreecommitdiff
path: root/compiler/GHC/HsToCore/Match/Constructor.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/HsToCore/Match/Constructor.hs')
-rw-r--r--compiler/GHC/HsToCore/Match/Constructor.hs41
1 files changed, 30 insertions, 11 deletions
diff --git a/compiler/GHC/HsToCore/Match/Constructor.hs b/compiler/GHC/HsToCore/Match/Constructor.hs
index 9c7ad46c22..96ab10fa4c 100644
--- a/compiler/GHC/HsToCore/Match/Constructor.hs
+++ b/compiler/GHC/HsToCore/Match/Constructor.hs
@@ -25,6 +25,7 @@ import GHC.HsToCore.Binds
import GHC.Core.ConLike
import GHC.Types.Basic ( Origin(..) )
import GHC.Tc.Utils.TcType
+import GHC.Core.Multiplicity
import GHC.HsToCore.Monad
import GHC.HsToCore.Utils
import GHC.Core ( CoreExpr )
@@ -98,7 +99,13 @@ matchConFamily :: NonEmpty Id
-> DsM (MatchResult CoreExpr)
-- Each group of eqns is for a single constructor
matchConFamily (var :| vars) ty groups
- = do alts <- mapM (fmap toRealAlt . matchOneConLike vars ty) groups
+ = do let mult = idMult var
+ -- Each variable in the argument list correspond to one column in the
+ -- pattern matching equations. Its multiplicity is the context
+ -- multiplicity of the pattern. We extract that multiplicity, so that
+ -- 'matchOneconLike' knows the context multiplicity, in case it needs
+ -- to come up with new variables.
+ alts <- mapM (fmap toRealAlt . matchOneConLike vars ty mult) groups
return (mkCoAlgCaseMatchResult var ty alts)
where
toRealAlt alt = case alt_pat alt of
@@ -110,7 +117,8 @@ matchPatSyn :: NonEmpty Id
-> NonEmpty EquationInfo
-> DsM (MatchResult CoreExpr)
matchPatSyn (var :| vars) ty eqns
- = do alt <- fmap toSynAlt $ matchOneConLike vars ty eqns
+ = do let mult = idMult var
+ alt <- fmap toSynAlt $ matchOneConLike vars ty mult eqns
return (mkCoSynCaseMatchResult var ty alt)
where
toSynAlt alt = case alt_pat alt of
@@ -121,9 +129,10 @@ type ConArgPats = HsConDetails (LPat GhcTc) (HsRecFields GhcTc (LPat GhcTc))
matchOneConLike :: [Id]
-> Type
+ -> Mult
-> NonEmpty EquationInfo
-> DsM (CaseAlt ConLike)
-matchOneConLike vars ty (eqn1 :| eqns) -- All eqns for a single constructor
+matchOneConLike vars ty mult (eqn1 :| eqns) -- All eqns for a single constructor
= do { let inst_tys = ASSERT( all tcIsTcTyVar ex_tvs )
-- ex_tvs can only be tyvars as data types in source
-- Haskell cannot mention covar yet (Aug 2018).
@@ -163,8 +172,15 @@ matchOneConLike vars ty (eqn1 :| eqns) -- All eqns for a single constructor
, eqn_pats = conArgPats val_arg_tys args ++ pats }
)
shift (_, (EqnInfo { eqn_pats = ps })) = pprPanic "matchOneCon/shift" (ppr ps)
-
- ; arg_vars <- selectConMatchVars val_arg_tys args1
+ ; let scaled_arg_tys = map (scaleScaled mult) val_arg_tys
+ -- The 'val_arg_tys' are taken from the data type definition, they
+ -- do not take into account the context multiplicity, therefore we
+ -- need to scale them back to get the correct context multiplicity
+ -- to desugar the sub-pattern in each field. We need to know these
+ -- multiplicity because of the invariant that, in Core, binders in a
+ -- constructor pattern must be scaled by the multiplicity of the
+ -- case. See Note [Case expression invariants].
+ ; arg_vars <- selectConMatchVars scaled_arg_tys args1
-- Use the first equation as a source of
-- suggestions for the new variables
@@ -229,12 +245,15 @@ same_fields flds1 flds2
-----------------
-selectConMatchVars :: [Type] -> ConArgPats -> DsM [Id]
-selectConMatchVars arg_tys (RecCon {}) = newSysLocalsDsNoLP arg_tys
-selectConMatchVars _ (PrefixCon ps) = selectMatchVars (map unLoc ps)
-selectConMatchVars _ (InfixCon p1 p2) = selectMatchVars [unLoc p1, unLoc p2]
+selectConMatchVars :: [Scaled Type] -> ConArgPats -> DsM [Id]
+selectConMatchVars arg_tys con = case con of
+ (RecCon {}) -> newSysLocalsDsNoLP arg_tys
+ (PrefixCon ps) -> selectMatchVars (zipMults arg_tys ps)
+ (InfixCon p1 p2) -> selectMatchVars (zipMults arg_tys [p1, p2])
+ where
+ zipMults = zipWithEqual "selectConMatchVar" (\a b -> (scaledMult a, unLoc b))
-conArgPats :: [Type] -- Instantiated argument types
+conArgPats :: [Scaled Type]-- Instantiated argument types
-- Used only to fill in the types of WildPats, which
-- are probably never looked at anyway
-> ConArgPats
@@ -242,7 +261,7 @@ conArgPats :: [Type] -- Instantiated argument types
conArgPats _arg_tys (PrefixCon ps) = map unLoc ps
conArgPats _arg_tys (InfixCon p1 p2) = [unLoc p1, unLoc p2]
conArgPats arg_tys (RecCon (HsRecFields { rec_flds = rpats }))
- | null rpats = map WildPat arg_tys
+ | null rpats = map WildPat (map scaledThing arg_tys)
-- Important special case for C {}, which can be used for a
-- datacon that isn't declared to have fields at all
| otherwise = map (unLoc . hsRecFieldArg . unLoc) rpats