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
This commit is contained in:
Scott Olsen 2021-05-22 09:15:22 -04:00 committed by GitHub
parent e7746c3d1e
commit 86e409fbd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

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