Skip to content

Commit 86e409f

Browse files
authored
fix: properly assign types to recursive calls (#1210)
This commit fixes an issue whereby all recursive calls were given var types, this resulted in strange behavior such as the following code: ```clojure (defn recurse [a b] (let [c (+ b 1) out (recurse c)] (+ out 1))) (defn main [] (println* (recurse 1 2))) ``` compiling just fine and yielding runtime segfaults. Now, if a recursive instance of a symbol was previously typed, we use that type--if not, we assign a fresh type variable (the old behavior). This fixes code like that above, throwing an error at compile time about an incorrect number of arguments for `recurse`. Fixes #348
1 parent e7746c3 commit 86e409f

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

src/InitialTypes.hs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,16 @@ initialTypes typeEnv rootEnv root = evalState (visit rootEnv root) 0
116116
-- catchall case for exhaustive patterns
117117
unknown -> pure (Left (InvalidObj unknown xobj))
118118
visitSymbol :: Env -> XObj -> SymPath -> State Integer (Either TypeError XObj)
119-
visitSymbol _ xobj@(XObj (Sym _ LookupRecursive) _ _) _ =
120-
-- Recursive lookups are left untouched (this avoids problems with looking up the thing they're referring to)
121-
do
122-
freshTy <- genVarTy
123-
pure (Right xobj {xobjTy = Just freshTy})
119+
visitSymbol e xobj@(XObj (Sym name LookupRecursive) _ _) _ =
120+
case E.searchValueBinder e name of
121+
-- If this recursive symbol is already typed in this environment, use that type.
122+
-- This is relevant for, e.g. recursive function calls.
123+
-- We need to use search here to check parents as our let-binding handling possibly puts recursive
124+
-- environments as the parent of a more local environment for the let bindings.
125+
Right (Binder _ found) -> pure (Right xobj {xobjTy = xobjTy found})
126+
-- Other recursive lookups are left untouched (this avoids problems with looking up the thing they're referring to)
127+
Left _ -> do freshTy <- genVarTy
128+
pure (Right xobj {xobjTy = Just freshTy})
124129
visitSymbol env xobj symPath =
125130
case symPath of
126131
-- Symbols with leading ? are 'holes'.

0 commit comments

Comments
 (0)