Skip to content

Commit 2205f4f

Browse files
committed
feat: initial support for recursive product types
This commit implements initial support for recursive product data types. In C, they're represented as structs that have a field that is a pointer to the same struct type. In Carp, we currently substitute recursive references with pointers to the type, and users must provide a pointer argument during instantiation. To make creating initial values of these types easier, we define a make function, which initializes a value of the type with its recursive part set to the null pointer.
1 parent df39477 commit 2205f4f

File tree

12 files changed

+260
-24
lines changed

12 files changed

+260
-24
lines changed

CarpHask.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ library
4747
PrimitiveError
4848
Project,
4949
Qualify,
50+
RecType,
5051
Reify,
5152
RenderDocs,
5253
Repl,

src/Constraints.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ solveOneInternal mappings constraint =
149149
Right ok -> solveOneInternal ok (Constraint ltA ltB i1 i2 ctx ord)
150150
Left err -> Left err
151151
else Left (UnificationFailure constraint mappings)
152+
-- Rec types
153+
Constraint (PointerTy a) (RecTy b) _ _ _ _ ->
154+
let (Constraint _ _ i1 i2 ctx ord) = constraint
155+
in solveOneInternal mappings (Constraint a b i1 i2 ctx ord)
156+
Constraint (RecTy a) (PointerTy b) _ _ _ _ ->
157+
let (Constraint _ _ i1 i2 ctx ord) = constraint
158+
in solveOneInternal mappings (Constraint a b i1 i2 ctx ord)
152159
-- Pointer types
153160
Constraint (PointerTy a) (PointerTy b) _ _ _ _ ->
154161
let (Constraint _ _ i1 i2 ctx ord) = constraint
@@ -231,6 +238,7 @@ checkConflictInternal mappings constraint name otherTy =
231238
case otherTy of
232239
PointerTy otherInnerTy -> solveOneInternal mappings (mkConstraint OrdPtr xobj1 xobj2 ctx innerTy otherInnerTy)
233240
VarTy _ -> Right mappings
241+
RecTy otherInnerTy -> solveOneInternal mappings (mkConstraint OrdPtr xobj1 xobj2 ctx innerTy otherInnerTy)
234242
_ -> Left (UnificationFailure constraint mappings)
235243
Just (RefTy innerTy lifetimeTy) ->
236244
case otherTy of

src/Deftype.hs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import ToTemplate
2121
import TypeError
2222
import TypePredicates
2323
import Types
24+
import RecType
2425
import TypesToC
2526
import Util
2627
import Validate
@@ -65,16 +66,18 @@ moduleForDeftype innerEnv typeEnv env pathStrings typeName typeVariables rest i
6566
[XObj (Arr membersXObjs) _ _] -> Right membersXObjs
6667
_ -> Left $ NotAValidType (XObj (Sym (SymPath pathStrings typeName) Symbol) i (Just TypeTy))
6768
validateMembers typeEnv env (candidate {typemembers = mems})
68-
--validateMemberCases typeEnv env typeVariables rest
6969
let structTy = StructTy (ConcreteNameTy (SymPath pathStrings typeName)) typeVariables
70-
(okMembers, membersDeps) <- templatesForMembers typeEnv env insidePath structTy rest
71-
okInit <- binderForInit insidePath structTy rest
72-
(okStr, strDeps) <- binderForStrOrPrn typeEnv env insidePath structTy rest "str"
73-
(okPrn, _) <- binderForStrOrPrn typeEnv env insidePath structTy rest "prn"
74-
(okDelete, deleteDeps) <- binderForDelete typeEnv env insidePath structTy rest
75-
(okCopy, copyDeps) <- binderForCopy typeEnv env insidePath structTy rest
70+
ptrmembers = map (recursiveMembersToPointers structTy) rest
71+
(okMembers, membersDeps) <- templatesForMembers typeEnv env insidePath structTy ptrmembers
72+
okInit <- binderForInit insidePath structTy ptrmembers
73+
okMake <- recursiveProductMakeBinder insidePath structTy ptrmembers
74+
(okStr, strDeps) <- binderForStrOrPrn typeEnv env insidePath structTy ptrmembers "str"
75+
(okPrn, _) <- binderForStrOrPrn typeEnv env insidePath structTy ptrmembers"prn"
76+
(okDelete, deleteDeps) <- binderForDelete typeEnv env insidePath structTy ptrmembers
77+
(okCopy, copyDeps) <- binderForCopy typeEnv env insidePath structTy ptrmembers
7678
let funcs = okInit : okStr : okPrn : okDelete : okCopy : okMembers
77-
moduleEnvWithBindings = addListOfBindings moduleValueEnv funcs
79+
funcs' = if (any (isRecursive structTy) ptrmembers) then (okMake : funcs) else funcs
80+
moduleEnvWithBindings = addListOfBindings moduleValueEnv funcs'
7881
typeModuleXObj = XObj (Mod moduleEnvWithBindings moduleTypeEnv) i (Just ModuleTy)
7982
deps = deleteDeps ++ membersDeps ++ copyDeps ++ strDeps
8083
pure (typeName, typeModuleXObj, deps)

src/Emit.hs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import qualified Meta
2424
import Obj
2525
import Path (takeFileName)
2626
import Project
27+
import RecType
2728
import Scoring
2829
import qualified Set
2930
import Template
@@ -814,11 +815,16 @@ templateToDeclaration template path actualTy =
814815
term = if "#define" `isPrefixOf` stokens then "\n" else ";\n"
815816
in stokens ++ term
816817

817-
memberToDecl :: Int -> (XObj, XObj) -> State EmitterState ()
818-
memberToDecl indent (memberName, memberType) =
818+
memberToDecl :: Ty -> Int -> (XObj, XObj) -> State EmitterState ()
819+
memberToDecl recty indent (memberName, memberType) =
819820
case xobjToTy memberType of
820821
-- Handle function pointers as members specially to allow members that are functions referring to the struct itself.
821-
Just t -> appendToSrc (addIndent indent ++ tyToCLambdaFix t ++ " " ++ mangle (getName memberName) ++ ";\n")
822+
Just rt@(RecTy t) ->
823+
if t == recty
824+
then appendToSrc (addIndent indent ++ "struct " ++ tyToCLambdaFix rt ++ " " ++ mangle (getName memberName) ++ ";\n")
825+
else appendToSrc (addIndent indent ++ tyToCLambdaFix t ++ " " ++ mangle (getName memberName) ++ ";\n")
826+
Just t ->
827+
appendToSrc (addIndent indent ++ tyToCLambdaFix t ++ " " ++ mangle (getName memberName) ++ ";\n")
822828
Nothing -> error ("Invalid memberType: " ++ show memberType)
823829

824830
defStructToDeclaration :: Ty -> SymPath -> [XObj] -> String
@@ -827,12 +833,18 @@ defStructToDeclaration structTy@(StructTy _ _) _ rest =
827833
typedefCaseToMemberDecl :: XObj -> State EmitterState [()]
828834
-- ANSI C doesn't allow empty structs, insert a dummy member to keep the compiler happy.
829835
typedefCaseToMemberDecl (XObj (Arr []) _ _) = sequence $ pure $ appendToSrc (addIndent indent ++ "char __dummy;\n")
830-
typedefCaseToMemberDecl (XObj (Arr members) _ _) = mapM (memberToDecl indent) (remove (isUnit . fromJust . xobjToTy . snd) (pairwise members))
836+
typedefCaseToMemberDecl (XObj (Arr members) _ _) = mapM (memberToDecl structTy indent) (remove (isUnit . fromJust . xobjToTy . snd) (pairwise members))
831837
typedefCaseToMemberDecl _ = error "Invalid case in typedef."
838+
pointerfix = map (recursiveMembersToPointers structTy) rest
832839
-- Note: the names of types are not namespaced
833840
visit = do
834-
appendToSrc "typedef struct {\n"
835-
mapM_ typedefCaseToMemberDecl rest
841+
-- forward declaration for recursive types.
842+
when (any (isRecursive structTy) pointerfix) $
843+
do appendToSrc ("// Recursive type \n")
844+
appendToSrc ("typedef struct " ++ tyToC structTy ++ " {\n")
845+
when (all (not . isRecursive structTy) pointerfix) $ appendToSrc "typedef struct {\n"
846+
--appendToSrc ("typedef struct " ++ tyToC structTy ++ " " ++ tyToC structTy ++ ";\n")
847+
mapM_ typedefCaseToMemberDecl pointerfix
836848
appendToSrc ("} " ++ tyToC structTy ++ ";\n")
837849
in if isTypeGeneric structTy
838850
then "" -- ("// " ++ show structTy ++ "\n")
@@ -859,7 +871,7 @@ defSumtypeToDeclaration sumTy@(StructTy _ _) rest =
859871
do
860872
appendToSrc (addIndent ind ++ "struct {\n")
861873
let members = zip anonMemberSymbols (remove (isUnit . fromJust . xobjToTy) memberTys)
862-
mapM_ (memberToDecl (ind + indentAmount)) members
874+
mapM_ (memberToDecl sumTy (ind + indentAmount)) members
863875
appendToSrc (addIndent ind ++ "} " ++ caseName ++ ";\n")
864876
emitSumtypeCase ind (XObj (Sym (SymPath [] caseName) _) _ _) =
865877
appendToSrc (addIndent ind ++ "// " ++ caseName ++ "\n")

src/Obj.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,12 @@ xobjToTy (XObj (Sym (SymPath _ "Static") _) _ _) = Just StaticLifetimeTy
823823
xobjToTy (XObj (Sym spath@(SymPath _ s@(firstLetter : _)) _) _ _)
824824
| isLower firstLetter = Just (VarTy s)
825825
| otherwise = Just (StructTy (ConcreteNameTy spath) [])
826+
xobjToTy (XObj (Lst [XObj (Sym (SymPath _ "RecTy") _) _ _, innerTy]) _ _) =
827+
do
828+
okInnerTy <- xobjToTy innerTy
829+
pure (RecTy okInnerTy)
830+
xobjToTy (XObj (Lst (XObj (Sym (SymPath _ "RecTy") _) _ _ : _)) _ _) =
831+
Nothing
826832
xobjToTy (XObj (Lst [XObj (Sym (SymPath _ "Ptr") _) _ _, innerTy]) _ _) =
827833
do
828834
okInnerTy <- xobjToTy innerTy

src/Primitives.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import Obj
2727
import PrimitiveError
2828
import Project
2929
import Qualify (Qualified (..), QualifiedPath, getQualifiedPath, markQualified, qualify, qualifyNull, qualifyPath, unqualify)
30+
--import RecType
3031
import Reify
3132
import Sumtypes
3233
import SymPath

src/RecType.hs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
module RecType
2+
(
3+
recursiveMembersToPointers,
4+
isRecursive,
5+
recursiveProductMakeBinder,
6+
)
7+
where
8+
9+
import Obj
10+
import Types
11+
import TypePredicates
12+
import TypeError
13+
import TypesToC
14+
import StructUtils
15+
import Template
16+
import Util
17+
import Data.Maybe (fromJust)
18+
import Concretize
19+
import ToTemplate
20+
21+
isRecursive :: Ty -> XObj -> Bool
22+
isRecursive structTy@(StructTy _ _) (XObj (Arr members) _ _) =
23+
any go members
24+
where go :: XObj -> Bool
25+
go xobj = case xobjTy xobj of
26+
Just (RecTy rec) -> rec == structTy
27+
_ -> False
28+
isRecursive _ _ = False
29+
30+
-- | Converts member xobjs in a type definition that refer to the type into pointers
31+
recursiveMembersToPointers :: Ty -> XObj -> XObj
32+
recursiveMembersToPointers rec (XObj (Arr members) ai at) =
33+
(XObj (Arr (map go members)) ai at)
34+
where go :: XObj -> XObj
35+
go x@(XObj (Sym spath _) i _) = if show spath == tyname
36+
then (XObj (Lst [XObj (Sym (SymPath [] "RecTy") Symbol) i (Just (RecTy rec)), x]) i (Just (RecTy rec)))
37+
else x
38+
go x = x
39+
tyname = getStructName rec
40+
recursiveMembersToPointers _ xobj = xobj
41+
42+
--------------------------------------------------------------------------------
43+
-- Recursive product types
44+
45+
recursiveProductMakeBinder :: [String] -> Ty -> [XObj] -> Either TypeError (String, Binder)
46+
recursiveProductMakeBinder insidePath structTy@(StructTy (ConcreteNameTy _) _) [XObj (Arr membersXObjs) _ _] =
47+
Right $
48+
instanceBinder
49+
(SymPath insidePath "make")
50+
(FuncTy (initArgListTypes membersXObjs) structTy StaticLifetimeTy)
51+
(recursiveProductMake StackAlloc structTy membersXObjs)
52+
("creates a `" ++ show structTy ++ "`.")
53+
where initArgListTypes :: [XObj] -> [Ty]
54+
initArgListTypes xobjs =
55+
map (fromJust . xobjToTy . snd) (remove (isRecType . fromJust . xobjToTy . snd) (pairwise xobjs))
56+
recursiveProductMakeBinder _ _ _ = error "TODO"
57+
58+
-- | The template for the 'make' and 'new' functions for a concrete deftype.
59+
recursiveProductMake :: AllocationMode -> Ty -> [XObj] -> Template
60+
recursiveProductMake allocationMode originalStructTy@(StructTy (ConcreteNameTy _) _) membersXObjs =
61+
let pairs = memberXObjsToPairs membersXObjs
62+
unitless = remove (isRecType . snd) . remove (isUnit . snd)
63+
in Template
64+
(FuncTy (map snd (unitless pairs)) (VarTy "p") StaticLifetimeTy)
65+
( \(FuncTy _ concreteStructTy _) ->
66+
let mappings = unifySignatures originalStructTy concreteStructTy
67+
correctedMembers = replaceGenericTypeSymbolsOnMembers mappings membersXObjs
68+
memberPairs = memberXObjsToPairs correctedMembers
69+
in (toTemplate $ "$p $NAME(" ++ joinWithComma (map memberArg (unitless memberPairs)) ++ ")")
70+
)
71+
( \(FuncTy _ concreteStructTy _) ->
72+
let mappings = unifySignatures originalStructTy concreteStructTy
73+
correctedMembers = replaceGenericTypeSymbolsOnMembers mappings membersXObjs
74+
in productMakeTokens allocationMode (show originalStructTy) correctedMembers
75+
)
76+
(\FuncTy {} -> [])
77+
where memberArg :: (String, Ty) -> String
78+
memberArg (memberName, memberTy) =
79+
tyToCLambdaFix (templatizeTy memberTy) ++ " " ++ memberName
80+
templatizeTy :: Ty -> Ty
81+
templatizeTy (VarTy vt) = VarTy ("$" ++ vt)
82+
templatizeTy (FuncTy argTys retTy ltTy) = FuncTy (map templatizeTy argTys) (templatizeTy retTy) (templatizeTy ltTy)
83+
templatizeTy (StructTy name tys) = StructTy name (map templatizeTy tys)
84+
templatizeTy (RefTy t lt) = RefTy (templatizeTy t) (templatizeTy lt)
85+
templatizeTy (PointerTy t) = PointerTy (templatizeTy t)
86+
templatizeTy t = t
87+
recursiveProductMake _ _ _ = error "concreteinit"
88+
89+
productMakeTokens :: AllocationMode -> String -> [XObj] -> [Token]
90+
productMakeTokens allocationMode typeName membersXObjs =
91+
let pairs = (memberXObjsToPairs membersXObjs)
92+
in toTemplate $
93+
unlines
94+
[ "$DECL {",
95+
case allocationMode of
96+
StackAlloc -> " $p instance;"
97+
HeapAlloc -> " $p instance = CARP_MALLOC(sizeof(" ++ typeName ++ "));",
98+
assignments pairs,
99+
" return instance;",
100+
"}"
101+
]
102+
where
103+
assignments ps = go (remove (isUnit . snd) ps)
104+
where
105+
go [] = ""
106+
go xobjs = joinLines $ assign allocationMode <$> xobjs
107+
assign alloc (name, ty) =
108+
let accessor = case alloc of
109+
StackAlloc -> "."
110+
HeapAlloc -> "->"
111+
in if isRecType ty
112+
then " instance" ++ accessor ++ name ++ " = " ++ "NULL ;"
113+
else " instance" ++ accessor ++ name ++ " = " ++ name ++ ";"
114+
115+
---- | Generate a list of types from a deftype declaration.
116+
--initArgListTypes :: [XObj] -> [Ty]
117+
--initArgListTypes xobjs =
118+
-- map (fromJust . xobjToTy . snd) (pairwise xobjs)
119+
120+
--tokensForRecInit :: AllocationMode -> String -> [XObj] -> [Token]
121+
--tokensForRecInit allocationMode typeName membersXObjs =
122+
-- toTemplate $
123+
-- unlines
124+
-- [ "$DECL {",
125+
-- case allocationMode of
126+
-- StackAlloc -> case unitless of
127+
-- -- if this is truly a memberless struct, init it to 0;
128+
-- -- This can happen, e.g. in cases where *all* members of the struct are of type Unit.
129+
-- -- Since we do not generate members for Unit types.
130+
-- [] -> " $p instance = {};"
131+
-- _ -> " $p instance;"
132+
-- HeapAlloc -> " $p instance = CARP_MALLOC(sizeof(" ++ typeName ++ "));",
133+
-- assignments membersXObjs,
134+
-- recAssignment recmembers,
135+
-- " return instance;",
136+
-- "}"
137+
-- ]
138+
-- where
139+
-- recmembers = filter (isRecType . snd) (memberXObjsToPairs membersXObjs)
140+
-- assignments [] = " instance.__dummy = 0;"
141+
-- assignments _ = go unitless
142+
-- where
143+
-- go [] = ""
144+
-- go xobjs = joinLines $ memberAssignment allocationMode . fst <$> xobjs
145+
-- unitless = remove isRecType (remove (isUnit . snd) (memberXObjsToPairs membersXObjs))
146+
-- recAssignment xs =
147+
--
148+
--memberAssignment :: AllocationMode -> String -> String
149+
--memberAssignment allocationMode memberName = " instance" ++ sep ++ memberName ++ " = " ++ memberName ++ ";"
150+
-- where
151+
-- sep = case allocationMode of
152+
-- StackAlloc -> "."
153+
-- HeapAlloc -> "->"
154+
155+
156+
--
157+
---- | The template for the 'init' and 'new' functions for a generic deftype.
158+
--genericInit :: AllocationMode -> [String] -> Ty -> [XObj] -> (String, Binder)
159+
--genericInit allocationMode pathStrings originalStructTy@(StructTy (ConcreteNameTy _) _) membersXObjs =
160+
-- defineTypeParameterizedTemplate templateCreator path t docs
161+
-- where
162+
-- path = SymPath pathStrings "init"
163+
-- t = FuncTy (map snd (memberXObjsToPairs membersXObjs)) originalStructTy StaticLifetimeTy
164+
-- docs = "creates a `" ++ show originalStructTy ++ "`."
165+
-- templateCreator = TemplateCreator $
166+
-- \typeEnv env ->
167+
-- Template
168+
-- (FuncTy (map snd (memberXObjsToPairs membersXObjs)) (VarTy "p") StaticLifetimeTy)
169+
-- ( \(FuncTy _ concreteStructTy _) ->
170+
-- let mappings = unifySignatures originalStructTy concreteStructTy
171+
-- correctedMembers = replaceGenericTypeSymbolsOnMembers mappings membersXObjs
172+
-- memberPairs = memberXObjsToPairs correctedMembers
173+
-- in (toTemplate $ "$p $NAME(" ++ joinWithComma (map memberArg (remove (isUnit . snd) memberPairs)) ++ ")")
174+
-- )
175+
-- ( \(FuncTy _ concreteStructTy _) ->
176+
-- let mappings = unifySignatures originalStructTy concreteStructTy
177+
-- correctedMembers = replaceGenericTypeSymbolsOnMembers mappings membersXObjs
178+
-- in tokensForInit allocationMode (show originalStructTy) correctedMembers
179+
-- )
180+
-- ( \(FuncTy _ concreteStructTy _) ->
181+
-- case concretizeType typeEnv env concreteStructTy of
182+
-- Left _ -> []
183+
-- Right ok -> ok
184+
-- )
185+
--genericInit _ _ _ _ = error "genericinit"

src/Scoring.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ depthOfType typeEnv visited selfName theType =
8888
-- accounts for unresolved types and scores based on these rather than
8989
-- relying on our hardcoded adjustments being correct?
9090
maximum (visitType ltTy : visitType retTy : fmap visitType argTys) + 1
91+
visitType (RecTy p) = visitType p
9192
visitType (PointerTy p) = visitType p
9293
visitType (RefTy r lt) = max (visitType r) (visitType lt)
9394
visitType _ = 1

src/TypePredicates.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ isUnit UnitTy = True
2020
isUnit (RefTy UnitTy _) = True
2121
isUnit _ = False
2222

23+
isRecType :: Ty -> Bool
24+
isRecType (RecTy _) = True
25+
isRecType _ = False
26+
2327
-- | Is this type a function type?
2428
isFunctionType :: Ty -> Bool
2529
isFunctionType FuncTy {} = True

src/Types.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ data Ty
5858
| UnitTy
5959
| ModuleTy
6060
| PointerTy Ty
61+
| RecTy Ty -- Recursive type, wraps members in a type definition.
6162
| RefTy Ty Ty -- second Ty is the lifetime
6263
| StaticLifetimeTy
6364
| StructTy Ty [Ty] -- the name (possibly a var) of the struct, and it's type parameters
@@ -195,6 +196,7 @@ instance Show Ty where
195196
show DynamicTy = "Dynamic"
196197
show Universe = "Universe"
197198
show CTy = "C"
199+
show (RecTy rec) = "Rec " ++ show rec
198200

199201
showMaybeTy :: Maybe Ty -> String
200202
showMaybeTy (Just t) = show t
@@ -248,6 +250,9 @@ unifySignatures at ct = Map.fromList (unify at ct)
248250
| otherwise = [] -- error ("Can't unify " ++ a ++ " with " ++ b)
249251
unify (StructTy _ _) _ = [] -- error ("Can't unify " ++ show a ++ " with " ++ show b)
250252
unify (PointerTy a) (PointerTy b) = unify a b
253+
unify (PointerTy a) (RecTy b) = unify a b
254+
unify (RecTy a) (PointerTy b) = unify a b
255+
unify (RecTy a) (RecTy b) = unify a b
251256
unify (PointerTy _) _ = [] -- error ("Can't unify " ++ show a ++ " with " ++ show b)
252257
unify (RefTy a ltA) (RefTy b ltB) = unify a b ++ unify ltA ltB
253258
unify (RefTy _ _) _ = [] -- error ("Can't unify " ++ show a ++ " with " ++ show b)
@@ -280,6 +285,9 @@ areUnifiable (StructTy (VarTy _) args) (RefTy _ _)
280285
| otherwise = False
281286
areUnifiable (StructTy _ _) _ = False
282287
areUnifiable (PointerTy a) (PointerTy b) = areUnifiable a b
288+
areUnifiable (RecTy a) (RecTy b) = areUnifiable a b
289+
areUnifiable (RecTy a) (PointerTy b) = areUnifiable a b
290+
areUnifiable (PointerTy a) (RecTy b) = areUnifiable a b
283291
areUnifiable (PointerTy _) _ = False
284292
areUnifiable (RefTy a ltA) (RefTy b ltB) = areUnifiable a b && areUnifiable ltA ltB
285293
areUnifiable RefTy {} _ = False
@@ -326,6 +334,7 @@ replaceTyVars mappings t =
326334
(RefTy a lt) -> replaceTyVars mappings (RefTy a lt)
327335
_ -> StructTy (replaceTyVars mappings name) (fmap (replaceTyVars mappings) tyArgs)
328336
(PointerTy x) -> PointerTy (replaceTyVars mappings x)
337+
(RecTy x) -> PointerTy (replaceTyVars mappings x)
329338
(RefTy x lt) -> RefTy (replaceTyVars mappings x) (replaceTyVars mappings lt)
330339
_ -> t
331340

0 commit comments

Comments
 (0)