+ full_msg = showSDoc (sep [text "No match in record selector", ppr sel_id])
+
+-- unbox a product type...
+-- we will recurse into newtypes, casting along the way, and unbox at the
+-- first product data constructor we find. e.g.
+--
+-- data PairInt = PairInt Int Int
+-- newtype S = MkS PairInt
+-- newtype T = MkT S
+--
+-- If we have e = MkT (MkS (PairInt 0 1)) and some body expecting a list of
+-- ids, we get (modulo int passing)
+--
+-- case (e `cast` (sym CoT)) `cast` (sym CoS) of
+-- PairInt a b -> body [a,b]
+--
+-- The Ints passed around are just for creating fresh locals
+unboxProduct :: Int -> CoreExpr -> Type -> (Int -> [Id] -> CoreExpr) -> Type -> CoreExpr
+unboxProduct i arg arg_ty body res_ty
+ = result
+ where
+ result = mkUnpackCase the_id arg arg_ty con_args boxing_con rhs
+ (tycon, tycon_args, boxing_con, tys) = deepSplitProductType "unboxProduct" arg_ty
+ ([the_id], i') = mkLocals i [arg_ty]
+ (con_args, i'') = mkLocals i' tys
+ rhs = body i'' con_args
+
+mkUnpackCase :: Id -> CoreExpr -> Type -> [Id] -> DataCon -> CoreExpr -> CoreExpr
+-- (mkUnpackCase x e args Con body)
+-- returns
+-- case (e `cast` ...) of bndr { Con args -> body }
+--
+-- the type of the bndr passed in is irrelevent
+mkUnpackCase bndr arg arg_ty unpk_args boxing_con body
+ = Case cast_arg (setIdType bndr bndr_ty) (exprType body) [(DataAlt boxing_con, unpk_args, body)]
+ where
+ (cast_arg, bndr_ty) = go (idType bndr) arg
+ go ty arg
+ | res@(tycon, tycon_args, _, _) <- splitProductType "mkUnpackCase" ty
+ , isNewTyCon tycon && not (isRecursiveTyCon tycon)
+ = go (newTyConInstRhs tycon tycon_args)
+ (unwrapNewTypeBody tycon tycon_args arg)
+ | otherwise = (arg, ty)
+
+-- ...and the dual
+reboxProduct :: [Unique] -- uniques to create new local binders
+ -> Type -- type of product to box
+ -> ([Unique], -- remaining uniques
+ CoreExpr, -- boxed product
+ [Id]) -- Ids being boxed into product
+reboxProduct us ty
+ = let
+ (tycon, tycon_args, pack_con, con_arg_tys) = deepSplitProductType "reboxProduct" ty
+
+ us' = dropList con_arg_tys us
+
+ arg_ids = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
+
+ bind_rhs = mkProductBox arg_ids ty
+
+ in
+ (us', bind_rhs, arg_ids)
+
+mkProductBox :: [Id] -> Type -> CoreExpr
+mkProductBox arg_ids ty
+ = result_expr
+ where
+ (tycon, tycon_args, pack_con, con_arg_tys) = splitProductType "mkProductBox" ty
+
+ result_expr
+ | isNewTyCon tycon && not (isRecursiveTyCon tycon)
+ = wrap (mkProductBox arg_ids (newTyConInstRhs tycon tycon_args))
+ | otherwise = mkConApp pack_con (map Type tycon_args ++ map Var arg_ids)
+
+ wrap expr = wrapNewTypeBody tycon tycon_args expr