emacs-elsa / Elsa

Emacs Lisp Static Analyzer and gradual type system.
GNU General Public License v3.0
640 stars 26 forks source link

Annotate variable definitions? #151

Closed TatriX closed 2 years ago

TatriX commented 5 years ago

I have a code like this:

(defconst pomidor-dir (file-name-directory (or load-file-name buffer-file-name)))

and I'm getting an error:

pomidor.el:66:23:error:Argument 1 accepts type String but received String?

which makes sense, load-file-name can be nil and the same applies to buffer-file-name.

But in this case result of the (or ..) form should always be a string as you either (load) it which means you have the former or you eval the buffer which means that you have the latter. Of course you can copy the code to the buffer which is not has no associated filename, but we can ignore this as you then probably don't care much about getting nil back.

So the question is: can I somehow guide analyzer asserting that I'm sure this must be a String. Or at least silence the warning?

Fuco1 commented 5 years ago

@TatriX yes, you can put a type annotation on top. So far we are using a "haskelly" syntax but it will change after #74 is solved.

The annotations actually did not work for defcustom and the fix I pushed recently is the one that broke master, so it won't work on the commit you're on right now, but here's how you do it:

;; (pomidor-dir :: String)
(defconst pomidor-dir (file-name-directory (or load-file-name buffer-file-name)))
Fuco1 commented 2 years ago

You can now write this. You will still get warnings that (or load-file-name buffer-file-name) can be nil and is being passed to file-name-directory, but this as you say can be ignored. When the variable itself will be used, it won't error. At some point I'm planning to add a type assert or some syntax to ignore an error, but that is not implemented. However, we should track it in a separate issue.

;; (pomidor-dir :: string)
(defvar pomidor-dir (file-name-directory (or load-file-name buffer-file-name)))

(file-name-directory pomidor-dir) ;; this will not error, `pomidor-dir' is assumed to be string