-
Notifications
You must be signed in to change notification settings - Fork 804
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
Fix missing TailCall warnings in TryWith/TryFinally #16328
Conversation
… non-tailrecursive calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice; that was fast!
Original comment
These could some good test cases, too. They already work in the release but it might be good to have them too to protect against regressions. Nevermind, I see that you already did this. Disregard this comment
// should warn
[<TailCall>]
let rec retryAsyncNonTc nRetries (work: unit -> 'a) : Result<'a, Exception list> =
try
Ok (work ())
with e ->
match retryAsyncNonTc (nRetries - 1) work with
| Ok _ as result -> result
| Error subExns ->
raise (AggregateException(e::subExns))
// should not warn
[<TailCall>]
let rec retryAsync prevExns nRetries (work: unit -> 'a) : 'a =
try
work ()
with e ->
let exns = e::prevExns
if nRetries < 1 then
raise (AggregateException(List.rev exns))
else
retryAsync exns (nRetries - 1) work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do actually wonder about Task though. Shouldn't a warning be emitted for those as well, since Task tailcalls aren't supported? Correct me if I'm wrong.
// should emit warning, I think?
[<TailCall>]
let rec f x = task {
let y = x - 1
let z = y - 1
return! f (z - 1)
}
You're right, the function you showed crashes with a StackOverflow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work!
While we're still here, a test for use
bindings might be good too, for more regression protection:
[<TailCall>]
let rec f () =
use x = makeDisposable()
f ()
Oh yeah, good idead. Pushed it. |
@dawedawe |
Oh good catch, thanks! I changed that while here. |
Fixes #16322 by adding the missing checks for TOp.TryWith and TOp.TryFinally.
Add a good amount of test cases.
Thanks again to @jwosty for raising the issue. I really had a blind spot there while I worked on this.