Unsafe evolution: handle extern members#81786
Conversation
Diagnostic bag is usually the last parameter. #Closed Refers to: src/Compilers/CSharp/Portable/Binder/Binder_Unsafe.cs:24 in 8569af4. [](commit_id = 8569af4, deletion_comment = False) |
| /// The member is explicitly marked as <see langword="extern"/> under the updated memory safety rules. | ||
| /// This can only appear for source symbols (after metadata roundtrip, this turns into <see cref="Explicit"/>). | ||
| /// </summary> | ||
| Extern, |
There was a problem hiding this comment.
In general, we prefer to treat source and metadata symbols uniformly. There are exceptions, but they usually happen when an information isn't preserved in metadata. In this case, however, it looks like the information is preserved "The member is explicitly marked", whether by unsafe or extern modifier. It is not clear to me why do we want to separate extern, this looks fragile and bug prone. I think explicit in source should get CallerUnsafeMode.Explicit value as it gets it when imported from metadata. #Closed
There was a problem hiding this comment.
when an information isn't preserved in metadata
See the speclet section and the corresponding discussion about this. extern is not preserved in ref assemblies apparently.
It is not clear to me why do we want to separate
extern
I guess I can merge the enum members (I originally separated them to have a different error message, but got rid of that since then for uniformity as you are saying).
There was a problem hiding this comment.
See the speclet section and the corresponding discussion about this.
externis not preserved in ref assemblies apparently.
I am not saying that extern members should be treated as safe. I am saying that the CallerUnsafeMode API should produce the same value from source and metadata.
There was a problem hiding this comment.
Yes, I agree. That part was replying to "There are exceptions, but they usually happen when an information isn't preserved in metadata" which technically is the case here (extern is not preserved in metadata)
There was a problem hiding this comment.
which technically is the case here (extern is not preserved in metadata)
No, this is not the case. The information is preserved, there is an attribute on the member, it really doesn't matter what syntax triggered its application.
There was a problem hiding this comment.
If there were no attribute, then the safety information wouldn't be preserved.
There was a problem hiding this comment.
Right, I will unify the Extern and Explicit members, thanks.
|
Done with a quick glance over the changes (commit 1) #Closed |
|
Please make sure we have tests that consume APIs through compilation references from a compilation that is using old rules and doesn't emit new attributes etc. The expectation is that the experience should match the experience of consuming metadata references produced from the same compilation. Retargeting scenarios are probably interesting too. To clarify, "from a compilation that is using old rules" refers to the referenced compilation rather than to the consuming compilation. #Closed |
We have that. All the tests use common helpers that always test both image and compilation references.
I can look into that (or maybe I'll write it to test plan), thanks. #Resolved |
Could you confirm that the safety mode is different between compilations? Perhaps you could point me to an example. #Closed |
(This isn't using a common helper after all since it's sufficiently different from the common scenarios, but still verifies both types of references.) #Resolved |
|
The scenario in referenced test doesn't look like one I have in mind. I am talking about scenarios where consumer uses new rules and the library uses old rules. It looks like the referenced test does the opposite. And such tests should not be limited to |
|
I guess my original comment was hard to "parse". I tried to clarify it #Closed |
| ReadOnlySpan<string> additionalSources = default, | ||
| Verification verify = default) | ||
| Verification verify = default, | ||
| CallerUnsafeMode expectedUnsafeMode = CallerUnsafeMode.Explicit) |
There was a problem hiding this comment.
I believe the default here makes sense, it should be rarely different.
In reply to: 3687547136 Refers to: src/Compilers/CSharp/Test/CSharp15/UnsafeEvolutionTests.cs:23 in 8569af4. [](commit_id = 8569af4, deletion_comment = False) |
I think the example I posted does exactly that - the library uses old rules (old rules are the default and the compilation in In reply to: 3687334849 |
This was modeled after ReportDiagnosticsIfObsolete for consistency (it should be also called at the same callsites). In reply to: 3687194228 Refers to: src/Compilers/CSharp/Portable/Binder/Binder_Unsafe.cs:24 in 8569af4. [](commit_id = 8569af4, deletion_comment = False) |
Test plan: #81207
Follow up on #81581 (i.e., still only for methods and properties).
Implements this speclet section: https://github.com/dotnet/csharplang/blob/d4a7252e082927c9e6d6f1386d0bb46fa690db8b/proposals/unsafe-evolution.md#extern