-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add [CallerMustBeUnsafe] attribute to denote APIs which should be called in an unsafe block #31354
Comments
And some of the Unsafe methods? |
Maybe. On one hand the developer already quite literally wrote |
Today, |
@huoyaoyuan You raise a good point. We need to set a bar for ourselves on where we want to apply this attribute. If the |
The safety of an API may also varies. For example |
I would like to raise a point about forward-compatibility - will this analyzer be optional? And if yes be on or off by default on net 5? These apis may be rarely used by avg developer but many companies develop programs that have at least one bottleneck where good throughput is bare minimum. If this analyzer will be forced in net 5 (via integrating directly to roslyn without ability to disable this particular feature) then upgrading from net core 3 and ealier to net 5 may suddenly be painful enough to put a stop to such endeavor due to errors (even if they will be mere warnings thats still a bit of a problem since it isnt unusual for companies to have warnings as errors by default) popping in many places where performance is critical. For completely new apis developed exclusively for net 5 and later forced unsafe block isnt a problem but for anything ealier it may be problematic. Just my 2 cents. |
@huoyaoyuan I already have a similar API proposal at https://github.com/dotnet/corefx/issues/42133. One of the downsides is that it might allow an explosion of APIs since there are many different combinations we'd want to allow. As a strawman, I wonder if it might be better to ship an API |
I also think that mixing language-safe/unsafe concepts with API safe/unsafe is not very good. The Now there are a lot of APIs that do things that can break you in recoverable and non-recoverable ways. For methods that shift sanity-checking on the programmer, these have been traditionally called Mixing the language concern with the API concern is theoretically possible, but then it needs to be done for all sorts of APIs and possibly still can't protect you from the results of using these APIs outside of unsafe contexts; think modifying a mutable span of a string - you would need an unsafe block to do that casts but if you later on use that mutable span elsewhere to do modifications you might be causing bad things to happen (and hours spent debugging because this will look like spooky action at a difference with interned strings). Many programmers work on the same project and if one opts into some unsafe actions for implementing a safe api, it doesn't mean that other programmers using safe APIs won't then be able to run into issues using this safe api in a different way. Another concern of mine is that an "you need 'unsafe' here" diagnostic will only make people enable unsafe blocks and use the language feature without thinking too much about it. Because that will be the StackOverflow answer explaining to you how to use that method. No thinking about how that will impact your program involved. |
Would also likely apply to https://github.com/dotnet/corefx/issues/32582. |
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = false,
Inherited = true)]
public sealed class CallerMustBeUnsafeAttribute : Attribute
{
}
} |
This may have non-obvious impact on generated code. There was previously discussion about runtime/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs Lines 1669 to 1677 in b5bb3c9
Here, Maybe a better solution would be to exclude generated code from |
Either excluding generated code, or just having the generator throw the pragma out saying it promises that it knows what it's talking about, seem fine. |
Note the cited RegexGenerator.Emitter.cs already does that for a few warnings; this would "just" be one (or more) more. runtime/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs Lines 30 to 39 in b5bb3c9
That said, I also opened an issue about trying to drive that list to zero 😄 |
Regarding naming: Should this be exclusive to C# or is there an expectation that the presence of a If not so, then I’d favor naming it agnostic to language constructs - e.g. |
Discussion on this topic in Discord just now came up with names like I'm actually liking |
How about |
Per dotnet/roslyn-analyzers#972, there's an outstanding feature for a Roslyn analyzer which would require a caller to use an
unsafe
block to make an API call that's pointer-equivalent dangerous but which doesn't take pointers.For example:
Whether that feature exists as a standalone analyzer or whether it gets moved into Roslyn proper (see dotnet/roslyn#8663), we still need to define the attribute in corefx and apply it to the appropriate methods.
API proposal
In this proposal I'm not applying
AttributeTargets.Class
orAttributeTargets.Struct
because I don't want constructs likeType t = typeof(SomeType)
to require anunsafe
block. TechnicallyAttributeTargets.Property
isn't needed because the property getter / setter can be annotated (same with events), but allowing it on properties seems like a decent convenience.The prime candidates to annotate are most methods on the
MemoryMarshal
type, some constructor-bypassing logic inFormatterServices
, and any "fast" object factories which allow bypassing normal constructor validation.Edit: I suppose since we've said that we see
ArrayPool<T>
as amalloc
equivalent and since it now returns uninitialized memory we should annotate its methods as well, but due to how widely used that type is that risks opening a huge can of worms.The text was updated successfully, but these errors were encountered: