Atlassian uses cookies to improve your browsing experience, perform analytics and research, and conduct advertising. Accept all cookies to indicate that you agree to our use of cookies on your device. Atlassian cookies and tracking notice, (opens new window)
Predicate-induced type inference
Key details
Description
This pattern seems to be fairly frequent:
(if (string? x)
(foo x)
(bar x))
It would be nice if the compiler could, based on the use of the predicate, infer that x is of type string in the then branch, and effectively behave as if the code were explicitly hinted:
(if (string? x)
(foo ^string x)
(bar x))
This would be useful in situations where the type could affect warnings or code gen. As a motivating example, consider the source for name
(defn name
"Returns the name String of a string, symbol or keyword."
[x]
(if (implements? INamed x)
(-name ^not-native x)
(if (string? x)
x
(throw (js/Error. (str "Doesn't support name: " x))))))
If x were inferred to be of type string in the then branch of the code above, then via function return type inference, name would be inferred to return type string (because -name is hinted).
(avoiding an unnecessary call to cljs.core.str.cljs$core$IFn$_invoke$arity$1, being much more efficient).
This kind of inference could be done for other core predicates, and even for code involving implements?. You could imagine that the expicit hint here could be removed:
This pattern seems to be fairly frequent:
(if (string? x) (foo x) (bar x))It would be nice if the compiler could, based on the use of the predicate, infer that
xis of typestringin the then branch, and effectively behave as if the code were explicitly hinted:(if (string? x) (foo ^string x) (bar x))This would be useful in situations where the type could affect warnings or code gen. As a motivating example, consider the source for
name(defn name "Returns the name String of a string, symbol or keyword." [x] (if (implements? INamed x) (-name ^not-native x) (if (string? x) x (throw (js/Error. (str "Doesn't support name: " x))))))If
xwere inferred to be of typestringin the then branch of the code above, then via function return type inference,namewould be inferred to return typestring(because-nameis hinted).Then, changes like https://clojure.atlassian.net/browse/CLJS-2864#icft=CLJS-2864Preview could make use of this information, with expressions like
(str (namespace x) "/" (name x))expanding to(js* "[~{},~{},~{}].join('')" (namespace x) "/" (name x))(avoiding an unnecessary call to
cljs.core.str.cljs$core$IFn$_invoke$arity$1, being much more efficient).This kind of inference could be done for other core predicates, and even for code involving
implements?. You could imagine that the expicit hint here could be removed:(if (implements? ISeq coll) (-first ^not-native coll) ...