-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Out parameters should behave like return values in a way - they get assigned a value from within the method body (this works), and they are "read" by the caller (this doesn't work). For example:
TryGetAnnotatedValue (out typeWithMethods);
typeWithMethods.RequiresPublicFields (); // Should IL2067 - mismatch of annotations
static bool TryGetAnnotatedValue([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] out Type typeWithMethods)
The local variable (or stack slot) is not assigned a value after the call to the method with out parameter.
This also means that this doesn't warn:
Type typeWithMethods = null;
TryGetAnnotatedValue (out typeWithMethods);
typeWithMethods.RequiresPublicFields ();
That's correct, but for a wrong reason - the typeWithMethods
is tracked throughout the method with a null
literal value, nothing else.
But this will warn, twice:
Type typeWithMethods;
TryGetAnnotatedValue (out typeWithMethods); // IL2062 - the `typeWithMethods` doesn't have a value -> unknown value we check it against the declared parameter
typeWithMethods.RequiresPublicFields (); // IL2062 - the out call above didn't assign value, so it's still "unknown"
This should not warn at all.
There probably other cases where this is broken. What I can see as two issues:
- The "input" value for a out parameter should only be checked if it's a parameter/field, so to simplify only if it's a value with annotation. Known (literal, string, type) or unknown values should not check anything and should be accepted as those will be overwritten.
- After the call with an out parameter, the value passed in should be "assigned" the value of the out parameter - so from that point on, it should be tracked as an annotated value (pointing to the out parameter as its source), regardless of what the value was before the call.
The second problem applies to ref parameters as well - the value of the variable/stackslot after a call with ref parameter should be an annotated value (pointing to the ref parameter), since the ref parameter acts like an out parameter after the call. On the other hand before the call, the value must be checked as normal in parameter.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status