-
Notifications
You must be signed in to change notification settings - Fork 789
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
Resolve issue with implicit yields requiring Zero #10556
Conversation
Since this would require conformance testing, here is a good location: Sadly tests are hard to make sense out of as various conformance stuff is strewn about in different projects and suites. I would add these for now:
Note that you can write the tests like so: [<Fact>]
let ``test-name``() =
FSharp """
// the F# source code
"""
|> compile
|> shouldSucceed or (perhaps preferred, up to you) [<Fact>]
let ``test-name``() =
FSharp """
// the F# source code
"""
|> typecheck
|> shouldSucceed or [<Fact>]
let ``test-name``() =
FSharp """
// the F# source code
"""
|> typecheck
|> shouldFail
|> withDiagnostics [ (Error 0, Line 0, Col 0, Line 0, Col 0, "the-message" ] Where the error is an error code, and the line/col numbers correspond to start/end ranges for the error, and the string message is the compiler message. alternatively, the |
From here it'll be easier to iterate on edge cases if you think of them |
Perfect - I'll get some tests wrapped around this and update the PR! |
Beyond the three obvious cases, I also added in the check for the implicit zeroing that occurs with if/else - if that's overkill or redundant (as I could see it being more a matter for how the parser generates the synexpr tree), just let me know. |
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.
Yes, this is a good change, thank you
Related to #8587
I've been wrapping my head around this in the idle hours for a couple of days now and this seems like it should resolve the bug in question. But I would appreciate eyes on it, and will with great joy take guidance on more elegant means of solving this.
Here's the low-down on the bug:
Based on the RFC - it's expected that a yielding CE require Zero (see Detailed Design - point 2)
In the code itself, we can see that the behavior makes sense:
CheckComputationExpressions.fs : 1440 states
And thus, relative to the samples in the ticket - the final 3, a raw expression, would be followed by a zero which would somewhat necessitate the need for that Zero method to exist.
The resolution for this that I have found is to do a safety-check with regards to how we handle ImplicitZero - if we're in a context where Implicit Yielding is enabled, then rather than erroring out if the builder lacks Zero, we can first check to see whether or not we're in an Implicit Yielding situation and therefore, if we are, rely on the translation context provided to handle the zero intelligently.
I've considered the placement of this logic - but cannot identify a better place to shim it in (without affecting more of the surrounding code than I feel comfortable with) than in
tryTrans
- while this results in a duplicate check around theenableImplicitYield
value (now intryTrans
and then nearly immediately afterwards in intranslatedCtxt
callback defined at :1452) - this seems minor.My intuition is that there's a cleaner way to handle this, but it may require more significant modifications to the surrounding behaviors here than what I have made here and, as such, I hesitate to do so without further insights.