-
Notifications
You must be signed in to change notification settings - Fork 847
Prevent assignment to literal ILFields #9797
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
Prevent assignment to literal ILFields #9797
Conversation
|
Interesting and great work, I was looking into the same issue, but got sidetracked :p. |
'mutably' sounds a bit weird to me, I'd suggest (considering that in F# we'd call it a literal, in other languages usually a constant, or a constant field): '%s' is a literal [or a constant] field, and cannot be assigned to. Or: Cannot assign a value to the literal [or constant] field '%s'. Or, simpler; Literals and constants are not assignable: '%s'.
@baronfel, I thought that was already the case? In the linked issue, it's shown that such fields cannot be assigned to. I agree it should be an error, apparently this is a condition protected by the CLR. |
8dbf518 to
a1ee1fe
Compare
Not necessary I think. Technically a change, but this is of the bugfix variety
Yes, we'll need a new warning for each case. Should be "Cannot assign 'foo' to a field marked as literal". A warning for |
|
@abelbraaksma good eye on the already-handled @cartermp As it is, I'm not sure that the compiler makes a distinction between those cases at the moment, from what I can see in Also @cartermp, you call out warning in your response. Can you share your rationale for warning vs error here? |
|
In this case it is technically a source breaking change. But I guess since it's a runtime error nobody is actually depending on being able to do this. |
|
I've made dedicated messages now, examples are in the issue submission. I went with @cartermp's phrasing, but quickly discovered that I needed different cases for when the Also, any pointers as to where tests should go? |
a6b9589 to
ef3d049
Compare
ef3d049 to
e9713c7
Compare
|
Any ideas how I can verify that my newly-added tests ran? I've scoured the output and build logs but I'm not seeing any output at all for the tests I wrote, or event any tests for the other module in the same file ( Is the test signature of |
|
I was able to invalidate my own assertion using |
We use xUnit instead in the ComponentTests, and it should be fine with such signature. I'm not sure how xUnit handles several modules though. Let me quickly check. |
|
I agree on the signature, I need to rollback my most recent commit as a result |
d479f29 to
e9713c7
Compare
@baronfel I suspect it can be because in the fsproj file, this particular file is listed with different path separator "/" vs "\" elsewhere. Maybe that's the reason test runner cannot run it. That would also explain why it runs just fine on my Linux laptop. I guess I need to introduce some safety mechanism of how many tests were discovered vs how many were executed. At least in CI. |
|
Good eye! I noticed that it ran (even though it immediately crashed) for me on MacOS as well. I'll make that change and see if the CI gets it. |
Thanks, I will talk to test platform folks tomorrow and ask them if it's by design. I would expect it to be normalized. Sorry, I overlooked it in the first place. |
You mean like hard crash? Was it inside compiler, or test framework? |
|
It was in the framework, but I had not done a proper rebuild via the shell script wrappers at the top-level of the repo. I was just using |
|
As a complete example, when I run |
|
Ah, gotcha. I will need to have PEVerify built when Test Utilities are built as well. I will create an issue for that and will fix, should be easy enough. |
|
Well, it's also not a huge deal to run |
|
It seems, there's one more issue - the namespace is incorrect in this particular test file (ErrorMessages, as oppose to Interop), not sure if it adds to a problem. Edit: yeah, I'm almost certain that the issue is in namespaces naming. For example There are several occurrences of such tests. I will try to fix them later today or first thing tomorrow morning (I'm in CEST). |
|
I went ahead and did this file (so I could start testing my tests :) ) |
One thing to note on the issue you create for this is that the path to the PEVerify binary needs to take into account that .Net Core builds |
Yeah, it has certain "history" :) Since we want all (non-vs) tests to run anywhere, it will be a must. |
|
@vzarytovskii after making that namespace change, there still seems to be no change in the set of test run. What I'm doing is going to the |
I usually go to Azure DevOps run, to tests tab, clear the filter and search for the test. I guess fsharpqa only runs the fsharpqa suite. But not others. |
|
I'm so confused, somehow searching for the exact fully-qualified test name didn't show when I tried the same as you. Yet searching for the word 'C#' did. Ah well, I'll take it either way 👍 @cartermp tests are in and green! |
cartermp
left a comment
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.
Minor nits, but otherwise looks great!
tests/FSharp.Compiler.ComponentTests/Interop/SimpleInteropTests.fs
Outdated
Show resolved
Hide resolved
tests/FSharp.Compiler.ComponentTests/Interop/SimpleInteropTests.fs
Outdated
Show resolved
Hide resolved
Co-authored-by: Phillip Carter <pcarter@fastmail.com>
…s.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com>
…s.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com>
|
Made those changes, good to go. |
KevinRansom
left a comment
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.
Thank you for this.
* Prevent assignment to literal ILFields * revert old mechanism * add new error message, use it, and provide localizations * add error message for literal and non-literal assignment * first stab at tests * flip directory separator in test project file * fix namespace on file to allow for it to be picked up * Update src/fsharp/TypeChecker.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update tests/FSharp.Compiler.ComponentTests/Interop/SimpleInteropTests.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update tests/FSharp.Compiler.ComponentTests/Interop/SimpleInteropTests.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com> Co-authored-by: Phillip Carter <pcarter@fastmail.com>
This PR closes #9785 by adding a check to
DelayedSets ofILFields.If the backing
ILFieldis a Literal, we should not allow the set. This check is pretty easy to do, but I imagine we would also want to do the following as part of this work:Error message
Regarding an error message, here is the current message for an incorrect mutable assignment:
I propose something like:
but I'm not sure what the 'call to action' would be in this case for the user. There's not a generally-suggestible action to take for something as straight-up incorrect as this.
Add some tests
There are a number of available constants in the BCL that I could set up a test that should fail for. I just need some pointers as to where the test should go, in light of the recent work on the test framework by @vzarytovskii.
Error vs Warning
I'm of the opinion that this is safely an error, as any current use of this construct fails at runtime and so isn't valid.
Other Non-assignable conditions
Since this is the place, should we also check to ensure that initonly fields are not set here?
Spec/Suggestions/RFC
Do we need one for this change? If so I can draft them.
Before and after
Here's a sample test FSI script I'm using to verify this change does in fact cause errors:
Under
dotnet fsishipped with5.0.100-preview.6.20318.15, the following output results:Under
dotnet fsibuilt from this change: