-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Make inline function attribute interact with defer expressions at callsites #6820
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
As if(
some_locked_resource.tryAcquireDeferRelease() //we get the optional value
//defers run now that we have this optional value
) |resource| {//if the optional result wasn't null, its value is copied (or aliased) and the if-block runs So what we would really need is to attach the { //add a new scope so our defers run after the if branch
const result = some_locked_resource.tryAcquireDeferRelease()
if(result) |resource| {
//...
}
} //now the `defer` and `errdefer` statements run And this translation needs to look even different for loops, so that we run Resource cleanup ideas have been discussed, discarded and re-opened before, see f.e. #494, #782, #5913. The other perspective, that the current |
In the example I was thinking that the defer attaches itself to the scope of the inline call's result location, so in a while-loop it would be placed at the end of the loop body. And regarding repurposing the inline keyword, I'd say that inline in Zig follows a theme of "inserting code" since it is also used to unroll loops. To me making it work with defer would be a natural extension of its current semantics. An The invisible control flow is admittedly an issue, maybe it could be explicit at the callsite somehow. |
The exact return type is an optional type, that is unwrapped into the |
Well, this goes for all uses of defer right. The problem in this case is that it is hidden at the callsite. |
@eriksik2 Correct, writing the defers in the corresponding location of the caller function (and introducing that anonymous scope) leads to the same result. |
Thanks for the proposal, @eriksik2. I'm going to close this proposal because my confidence level that this will not end up making it into the language is high. |
Right now marking a function inline is meaningless in that it doesn't change the meaning of code, it only changes how it is compiled. (If the compiler didn't already decide to inline, in which case it doesn't do anything). This makes inline hard to use effectively without resorting to some mental heuristic like "if function short or called often then inline". But this is probably similar to the heuristic the compiler uses so it still doesn't really do anything!
Inline could be made more useful while still serving its current use case, and even become a facility for things like scoped resource cleanup and performance tracing by making defer and errdefer respect inline. errdefer/defer in an inline function would run at the end of the callsite scope. This can only work if the callee is inline since defer can reference local values that still need to be in scope when they run.
Example usecase:
This is a good solution to scoped resources I think since it makes you be explicit: you have to call tryAcquireDeferRelease instead of tryAcquire in the example. And it doesn't insert any hidden cleanup code, it only reorders code according to the already existing rules that defer has.
A downside is that if you forget to mark a function inline the defers would run before returning as usual and any resource you return would be quietly invalidated, but the code would still compile if the invalidation doesn't involve a
this.* = undefined;
. (At least I think that would catch it). Alternative could be to have a specialinline defer
or something, to explicitly defer something to the caller. (But mixinginline defer
and normal defer in the same function would be forbidden since it would break the defer execution ordering).The text was updated successfully, but these errors were encountered: