Odin
Odin copied to clipboard
Procedure declaration in defer block crashes compiler
Compile following with odin build .
package main
main :: proc()
{
defer
{
foo :: proc(x: int) {return x}
}
}
You should get:
D:\a\Odin\Odin\src\llvm_backend_stmt.cpp(42): Assertion Failure: `e != nullptr`
Context
Odin: dev-2022-08-nightly:4c3281b3
OS: Windows 10 Professional (version: 21H2), build 19044.1826
CPU: Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz
RAM: 16330 MiB
Also interesting that this gives you undeclared name: foo
:
package main
main :: proc()
{
defer
{
foo :: proc(x: int) {return x}
foo(1)
}
}
This begs the question, is this something we should allow in the first place?
defer
really is an edge in many ways (e.g. it disallows return
within it for loads of sanity reasons (not technical))
This begs the question, is this something we should allow in the first place?
I'm inclined to say no. There's no good reason foo
couldn't be a child proc of main
or even its own top-level proc.
If extrapolated to a larger codebase, it would also be more maintainable to enforce defer
hosting only simple expressions and statements, not procedure definitions.
defer
blocks by design are meant to be a compact "clean up what we did just above" kind of block. If that cleanup is complicated, put it in its own procedure and call that, e.g. defer destroy_thing(thing)
.
This begs the question, is this something we should allow in the first place?
I think many users, myself included, would have expected constant declarations ::
inside a defer
block to work. Variable declarations are also allowed inside a defer
block. So the user thinks that they are allowed to write normal code within defer
as if it were just a simple copy of contents to the end of the containing scope. A more restrictive defer
means that the language rules become more complex and less intuitive.
But @Kelimion's arguments also make a lot of sense to me.
The issue isn't ::
but rather procedure declarations with defer
(I know what the bug is and how to fix it).
I'm wondering what the best approach to this is. Understand that this is not a technical problem but a design problem. You could easily have as many constant value and type declarations as you want within a defer
.