code
def hi
id = "unused code"
puts "hi"
end
hi
output
╰─❯ crystal run test.cr
hi
I’m pretty sure it can/does and is just not included in the final binary, in --release
mode at least.
No warnings hint at all
❯ crystal run --release test.cr
hi
Correct, that’s not something the compiler currently handles. GitHub - crystal-ameba/ameba: A static code analysis tool for Crystal might be able to call out unused variables and such like that tho.
ameba does not work for this , it seems that it can only detect code style
In this particular case, I think you have to explicitly enable the rule Lint/UselessAssign
, then you’d get:
[W] Lint/UselessAssign: Useless assignment to variable `id`
> id = "unused code"
^^
Finished in 587 microseconds
1 inspected, 1 failure
The compiler doesn’t warn you, but --release
mode will throw the code away as Blacksmoke16 says.
You can check with:
crystal build --emit asm hi.cr
vs.
crystal build --emit asm --release hi.cr
There is no unused code string in the --release
generated assembler (*.s
file).
You can also search for strings directly in binary files.
crystal build test.cr
strings test | grep unused
# unused code
crystal build test.cr --release
strings test | grep unused
#
The following commands are sometimes useful
crystal tool unreachable
def hi
puts "hi"
end
def meow
puts "meow meow"
end
hi
crystal tool unreachable hi.cr
hi.cr:5:1 ::meow 3 lines
I think you are looking for the unreachable tool. See
https://crystal-lang.org/2023/10/09/1.10.0-released/
I know this but it doesn’t seem to work for the example
╭╴🪟 $nu hello_crystal on main [?] via 🔮 v1.12.1 took 3s
╰─❯ crystal tool unreachable test.cr
╭╴🪟 $nu hello_crystal on main [?] via 🔮 v1.12.1 took 4s
╰─❯
The unreachable tool only points out unused methods, not local vars and such.
Yeah, unreachabel
doesn’t work for this. The assignment is reachable. Its effect just doesn’t matter for anything.
@aiac I’m not sure what your expectation of the compiler is here. Why do you think it should produce a warning?
I recognize that some compilers provide warnings for things like this, but the existence of a dedicated linting tool like Ameba as well as dead-code elimination in LLVM mean there’s really no reason to do this in the compiler. Admittedly, the linter likely exists because the compiler doesn’t lint your code. Chicken vs egg, but the point is that there’s a dedicated tool for static analysis that does a pretty good job.
And since LLVM is also exceedingly good at dead-code elimination, making the compiler detect dead code that LLVM eliminates anyway would be wasted effort. For perspective, LLVM is so good at eliminating dead code that many Crystal benchmarks have to explicitly avoid it via side effects so benchmark blocks won’t be completely eliminated.
Maybe you could argue that Ameba could be rolled into the compiler (as crystal tool lint
or similar), but “the compiler doesn’t detect it” isn’t a useful complaint when there is no need for the compiler to detect it.