swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.38k stars 10.34k forks source link

[SR-978] Warn on do {} with only one empty catch {} block #43590

Open jckarter opened 8 years ago

jckarter commented 8 years ago
Previous ID SR-978
Radar None
Original Reporter @jckarter
Type Improvement
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Improvement, StarterBug | |Assignee | MultiColourPixel (JIRA) | |Priority | Medium | md5: d5f41243d2aaf067f1ecd57198c44970

Issue Description:

Eric Knapp caught some sample code in the wild unwisely using an empty catch block to swallow errors:

https://twitter.com/ejknapp/status/710589235464523776

We should warn on this to encourage people to use try! to trap on unexpected errors instead.

belkadan commented 8 years ago

How do you silence the warning?

jckarter commented 8 years ago

Morally, if you don't expect any errors to happen, you should use try! to assert that. Practically, if you really want to throw away errors, there's _ = try?.

belkadan commented 8 years ago

Yes, but what about "I want to catch this particular error, but ignore any others?" ("I want to ignore this particular error" is easy enough to special-case.)

jckarter commented 8 years ago

I see what you're saying. IMO, if you do that, we should let it pass:

do {
  try something()
} catch Foo.Error {
  handleFooError()
} catch {
  /* do nothing */
}

IMO, it's only the case where you do nothing more than do { ... } catch {} that deserves a warning.

swift-ci commented 8 years ago

Comment by Josef Willsher (JIRA)

I’m happy to implement this. How should we handle cases where the do block contains more than 1 expression—we can't issue a fixit here, but should I still emit a warning?

jckarter commented 8 years ago

If the do block contains multiple statements, you should still be able to change every try to try! or try? inside it.

swift-ci commented 8 years ago

Comment by Josef Willsher (JIRA)

try? has different semantics to try though — you won't be able to just interchange them in an expression like foo(a: try getA()).

Are you sure its not too much compiler gymnastics for a fixit to change a whole scope's try expressions to the trapping try!? I think it is reasonable to do for a single expression, but if the do block contains a significant amount of code, surely the better alternative is to get the user to rethink it themselves?

I already have it emitting a warning for a single, empty, unguarded catch block, and I’m happy to implement the fixit either way.

jckarter commented 8 years ago

Sure, it might be reasonable to just warn without fixits if the `do` block is too complex.

belkadan commented 5 years ago

Resetting assignee for all Starter Bugs not modified since 2018.