crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.48k stars 1.62k forks source link

[Discussion] Knowing all possible errors #7154

Open vladfaust opened 5 years ago

vladfaust commented 5 years ago

I often find myself digging into the source code, sometimes quite deep, to find out which errors to rescue on a particular line of code. Even if some of possible errors are described in docs, there may be inner method calls which would raise those which are not mentioned.

It either comes with experience -- you start to keep in mind all possible errors, or you catch those unexpected thus unhandled errors in production.

I'd like to discuss an enhancement -- a way to know all possible errors a line of code or method could raise. It could be a crystal tool like expand. Errors could also be exported on docs generation and imprinted into the HTML.

Additionally, there could be an annotation marking a method as no-errors, i.e:

@[Safe]
def foo(bar : String)
  bar.to_i
end

And if a compilation-time analyzer finds that there are unrescued errors within the method body, it would deny to compile telling us about these possible errors:

Error not rescued in a safe method: ArgumentError in foo:

  bar.to_i
      ^

Or even imagine compiling a program with --safe flag which would ensure no error ever could be raised in this program! 😦

WDYT apart from "it's very hard to implement" and "we have other issues to work on"?

j8r commented 5 years ago

That's similar to checked exceptions in Java. I'm against. Kotlin have evaluated them, the conclusion is checked exceptions don't provide any/enough benefit to be worth implementing them.

In your example, you can use the nillable variant of to_i:

def foo(bar : String) : Int32
  bar.to_i?
end

This will give a compile time error because the return type can be Nil. See also https://github.com/crystal-lang/crystal/issues/6987

vladfaust commented 5 years ago

@j8r I find Kotlin example irrelevant, because

It says that every time I append a string to something (a StringBuilder, some kind of a log, a console, etc.) I have to catch those IOExceptions

And I don't speak about enforcing rescuing errors, I want to let the developer know which errors are possible -- this is the original idea.

Moreover, @[Safe] and --safe should be optional, of course.

vladfaust commented 5 years ago

Usecase -- background jobs processing. I want to be sure a Job's perform method never raises. Isn't that great? It would be a very bold feature.

asterite commented 5 years ago

I don't think that will work. Soon a + b might raise because of overflow. And that's the most basic operation you can do.

If you want to ensure that perform doesn't raise, add a rescue block at the end and log the exception, and retry the job later.

Blacksmoke16 commented 5 years ago

PHPdocs have http://docs.phpdoc.org/references/phpdoc/tags/throws.html. IDEs can use that to let you know of unhanded exceptions as well as generated docs of what exceptions each method may throw and what would cause it.

refi64 commented 5 years ago

There's always the Swift route, where a function is simply marked as throws and the compiler infers / checks the errors.

bcardiff commented 5 years ago

The best that can be done is to have a tool that analyze the exception that a given method could potentially raise, but this will require an entry point + cursor like the implementation tool.

Unless you compile and resolve types you wont know for sure what is raised.

Regarding OverflowErrors, some hierarchy could be used to split RuntimeError / StandardError similar as in ruby and avoid false positives.

ysbaddaden commented 5 years ago

I second the creation of a tool. Using the Crystal parser and a custom AST visitor, it should be possible to infer which exceptions are raised inside a function.

It would be a very nice tool to have.

girng commented 5 years ago

am not sure. all the errors i get, i get a full stack trace to the exact character (most of the time), and line of code. and its nicely printed to the console already. like in your original post the ^ points to it already. my example

however, some errors that say: please report issue on github, etc are very rare (happened only last year, and when i was still learning crystal). never had that crash happen yet. i think error reporting is very sufficient imo

crysbot commented 9 months ago

This issue has been mentioned on Crystal Forum. There might be relevant details there:

https://forum.crystal-lang.org/t/exception-safety/6604/2