Skip to content

Unreachable :else branch when unchecked var is inside a cond branch #187

Description

@sookcha

Original Discussion in Slack

For example, when I write code like below, it should fail on type check using (t/check-ns-clj 'typed-example.unchecked-flow {:check-config {:unannotated-var :unchecked}}) but it says :ok.

(ns ^:typed.clojure typed-example.unchecked-flow
  (:require [malli.core :as m]))

;; Typed function that expects an int
(m/=> requires-int [:-> :int :string])
(defn requires-int [x] (str "Got: " x))

;; Unannotated function (gets Unchecked type)
(defn unannotated-fn [x] x)

;; BUG: This should FAIL type checking but PASSES with :unchecked
(defn demonstrate-bug []
  (let [unchecked-val (unannotated-fn 42)]
    (cond
      (string? unchecked-val) "it's a string"
      ;; This :else branch should be type-checked but isn't!
      :else (requires-int "NOT-AN-INT"))))

I suspect that if there's a unchecked var inside cond branch, typed clojure assumes that :else branch is always unreachable?
So I changed typed.cljc.checker.check.if a bit to fix this.

(defn check-if [...]
  (let [unchecked-mode? (= :unchecked (get-in opts [::vs/check-config :unannotated-var]))
        chk-thn #(let [[env-thn reachable+] (update-lex+reachable lex-env fs+ opts)
                       forced-reachable+ (or reachable+ unchecked-mode?)]
                   {:env-thn env-thn
                    :cthen (check-if-reachable then env-thn forced-reachable+ expected opts)})
        chk-els #(let [[env-els reachable-] (update-lex+reachable lex-env fs- opts)
                       forced-reachable- (or reachable- unchecked-mode?)]
                   {:env-els env-els
                    :celse (check-if-reachable else env-els forced-reachable- expected opts)})]))

This way the problem solved.
Or, maybe we can fix reachability on env+ and remove* function to properly address unchecked type.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions