-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Warn on if method_that_only_returns_nil
#12365
Comments
Feel like this would be something better suited to https://github.com/crystal-ameba/ameba? |
IIRC they rejected it because Ameba is strictly limited to syntactic analysis and this requires type inference. |
Hmm, couldn't it be inferred just via the syntax by seeing a method has an explicit falsely return type while being used in conditional logic? Otherwise, yea that's fair. |
What I see most in linters is "things that are probably harmless but may be difficult to grok", like variable shadowing or useless assignment. If you have this particular construct in your code, though, it seems almost certain to be a bug. I can't imagine a case where it wouldn't be, at least. And in cases like this, should we need to opt into a third-party tool to tell us we're doing something obviously incorrect, or should we be able to rely on the compiler to tell us? Honest question, I don't have the Best Answer™, though I do have a preference for not having to opt in. |
Yea I guess my thinking is this would be the first case of the compiler warning the user about something they've done versus a more language level thing like a deprecation. At least until #9246, which might warrant some higher level discussion, as you point out, on how (or if) that should exactly work. E.g. should they be any different than the internal compiler warnings themselves. Or what qualifies for the compiler to warn you about as there are lot of things and bugs you can have in your code. I can't imagine it being maintainable to identify and handle all of them. A related thought is this is exactly why you write tests, as it's able to point out obvious bugs like this without requiring any extra compiler logic. |
This is a good point, especially because I'm suggesting it as a warning. There is precedent for the compiler protecting you from things like this in Crystal, though. One example is when you define
This is actually how I noticed the bug. 😄 A unit test was telling me the return value was |
Instead of a warning, we could make it an error. That said, in general in Crystal it's impossible to make these errors or warnings without preventing valid code from compiling. I actually tried this change just now, and the compiler can't compile itself anymore. The std specs can't compile anymore. And they all have valid code! Here's a contrived example: class Foo
def companion : Nil
nil
end
def do_it
puts "Foo is doing it!"
end
end
class Bar
def companion
Foo.new
end
def do_it
puts "Bar is doing it!"
end
end
def logic(entity)
if entity.companion
puts "Some special logic if the entity has a companion"
end
entity.do_it
end
logic(Bar.new)
logic(Foo.new) The last line, The main issue is that a single method can be instantiated differently for different types. I guess to make it work we'd have to check if for all possible instantiations it's always |
I think this would be a bad idea. Consider code like
With the suggestion the first call to x would warn. Or in other words: This break duck typing for methods returning falsey values. Error on explicit return against a declared EDIT: Uh, perhaps I should learn to read. This is basically what asterite write above 😓 |
I don't think this is something for the compiler to care about. Neither
I agree, that should be a good reason for the compiler to refuse code. |
Are we talking about the same thing? None of the code examples provided here have an explicit |
@jgaskins I just updated my example with a Nil return type. |
@asterite Hmm, I just ran a variant of your code example (I added However, in both invocations, the compile-time type is the single concrete type that's passed into the At the very least, this helps explain why this is so much less straightforward than I imagined. 😕 |
Methods are compiled differently each time the input types are different. |
A method with a Lines 128 to 137 in 5de237e
The abstract method crystal/src/http/server/handlers/websocket_handler.cr Lines 21 to 24 in 5de237e
A similar call can be found in crystal/src/http/server/handler.cr Lines 26 to 32 in 5de237e
Of course, a purely syntactic linter won't be able to tell the return type of Also weren't those explicit returns recently discussed somewhere else? |
I had a bug caused by something similar to this state = {key: "value"}
if state == "value"
# do some stuff
end Simple mistake that took hours of debugging to work out. |
But supposedly the type of problem @stakach is mentioning has been implemented in Ameba (based on the discussion that started in #10277): crystal-ameba/ameba#237 |
Yes, crystal-ameba/ameba#237 technically goes at that problem, but only in a very reduced, almost negligible scope: It only considers equality operations between two literals. |
Feature Request
Given this code:
Checking for truthiness of the return value of
method_that_only_returns_nil
will never enter the block, and that might be a useful compiler warning.An example of this I just ran into is that I usually use this type annotation when I'm using a method for its side effects, but I decided to add a return value later and forgot to change/remove the type annotation. A warning here would've saved me significant debugging time. 😄
A stretch goal here might be to warn any time you explicitly
return
a non-nil value with aNil
return type.The text was updated successfully, but these errors were encountered: