-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Lint for functions that don't return, but aren't written as "-> !" #448
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
Comments
Probably should be a pedantic lint. |
Also bail for trait impls. We have a lot of |
I'm trying to imagine this lint existing. If it did, couldn't it be used to solve the Halting Problem? Let's try to prove that this lint cannot exist. Let's say I have a Rust Function, and I run this lint on it.
Let's say now that I make a compiler that translates a Turing Machine and its initial Tape into a Rust function. This is possible and not very hard, but the details of that compiler I will leave aside because they're not important. An implementation detail, however, will be that the resulting function will return the bit that the Head of the TM points to after it halts. Okay. Almost there. Let's say we grab some Turing Machine fn f() -> bool Now, we will run Clippy with this lint turned on.
If, respectively, Therefore, we have used this lint to solve the Halting Problem. Which we know to be impossible. Therefore, this lint cannot possibly exist. |
@llogiq who can I ping to proofread me? I think I've successfully proven that this lint is impossible 🤔 |
Rust already has a compiler-level understanding of divergence, which does not require solving the Halting Problem, because the Halting Problem is about proving whether a function does or doesn't terminate, whereas Rust's divergence is a subset of that: Rust has functions which definitely do not terminate and then "the rest". You can prove that a function definitely does not terminate if all of its branches are diverging (this means: calling diverging functions/panics, or using |
Most such theoretical concerns are not super relevant in the practical world where you seldom need 100% perfection. Dependency resolution is also NP-complete. Doesn't stop Cargo from trying anyway, it just bails in pathological cases. It's good enough! |
That's good and all that, but we have to be clear on something: the lint, as proposed originally in this issue, is impossible. That much is true, unless there's a mistake in my proof. The entire issue discusses a lint that absolutely decides whether or not a function diverges. That would be a nice lint to have, but it ultimately does not exist. What you propose is a different lint. |
Is that an useful enough subset of divergence for the users of |
NP-complete is not the same as Undecidable, Manish. One is possible, the other is not :)
Fair enough. Let's propose a different lint to the one this post was about: one that is incomplete but exists. I think both of us agree on this. The perfect divergence lint, which is what was being proposed, doesn't exist. Let's make an imperfect one, if it can be useful enough. |
The way I understand this issue is that the lint would check for functions where the function block has a I don't think this is proposing something stronger than that. It wouldn't really make sense either I don't think; even if we did have the perfect lint that could detect functions that don't return, telling the user to annotate their functions with There's actually a lint that's somewhat similar: |
Uh, it's absolutely possible. T issue doesn't actually provide parameters for a lint, so arguing about "the lint proposed in the issue" is kinda moot. It's pretty clear to the multiple clippy team members in this thread that there is a possible lint that (a) handles the code in the original issue (b) is useful and (c) is implementable. If you've imagined a different lint specification that was not written anywhere, you're free to prove it's impossible all you like but it's kinda irrelevant to talk about it here. The original issue was this code: fn f() -> int {
fail!("f")
}
fn main() {
f();
} translated to modern Rust: fn f() -> isize {
panic!("f")
}
fn main() {
f();
} Rust absolutely knows that fn f() -> ! {
panic!("f")
} Rust does not know that
@y21 is bang on the mark here, there is no other way this lint could work. it MUST restrict itself into being annoying about functions that rustc can prove diverge, because there's not much more you can do here to appease the lint beyond changing the return value of the function to |
The parameters are right there in the title, see? Lint for functions that don't return, but aren't written as "-> !" That's a clear a functional requirement as any.
Again, written right there in the title.
I see. I misunderstood the reference in the original post. It says "see X", where X is a closed issue in the rust repo, which I did not expect to mean "this would be a continuation of the work in X". Alright, my bad. The title is still pretty misleading, though. |
... that's just being pedantic. I'm not sure if you're being serious, but we do not typically expect issue titles to be exact specifications. Grice's maxim of quantity encourages brevity in the case of unambiguity. I wouldn't think it's necessary, but if you really feel the need for this: feel free to imagine ".. within the scope that it is possible" on every issue title on the clippy repo. We have many lints that are "lint on X (within the scope that is possible)", it's implicitly assumed, more or less. |
See rust-lang/rust#12836
The text was updated successfully, but these errors were encountered: