-
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
AssignmentPatterns can break with two out parameters from the same method #85464
Comments
The problem is using the Origin as the key for assignments, we will need to come up with something better. We've already ran into this problem with return values and solved it by adding a boolean to the key, but that's not enough for this case. I think we may need to add a "custom" key part - a differentiator. Each place where we create an assignment pattern will need to specify this (could be empty). We already have two such use cases (return values and out parameters), but there may be more. Note that we can't get rid of the imprecise Origin either - if there are two callsites to the same method in the same method body we need the IL offset to differentiate between them. So it has to be a composite key with Origin being one part of it. |
@jtschuster @sbomer - I welcome any ideas how to solve this. |
dotnet/linker#2875 adds a test which hits this. |
My first thought is that we could copy the same logic as return values if we have a Or maybe we could use the targeted (Field/LocalVariable/Parameter)Definition with the origin as the key |
I think this is very close to what I proposed above. The main difference is that I'm not sure we should handle this in the Honestly the current code is relatively weird already, since it will handle return values only if they're the only target - which I think is correct, but it makes assumptions which I would like to keep out of the general store. |
This was needed to fix failures in libraries build with AOT. The underlying problem is not fully fixed: https://github.com/dotnet/linker/issues/2874 But with these changes it doesn't crash the compiler, it just leads to sometimes imprecise warnings.
If we can handle it inside of the pattern store, I would do that. I see the pattern store not as a general-purpose thing, but as modeling the specific kinds of source/target mismatches we can encounter in the dataflow. Letting callers introduce their own context would make it harder to reason about the kinds of patterns track. The return value logic is just a workaround for this bug: dotnet/linker#2778. What information do we need to disambiguate the ref param case? I think it would be enough to just store the index of the parameter. For out params, the source will just be the annotated out parameter. For ref params since the parameter acts as both a source and a target, we'd end up merging the patterns and storing {annotated ref parameter, passed-in annotated value} as both the source and target. This would have some redundant cases since it will check the parameter against itself and the annotated value against itself, but I think it captures the behavior we want. |
Tagging subscribers to this area: @dotnet/area-system-reflection Issue DetailsCurrently we track each assignment pattern based on its Origin - which really means method + IL offset. So if the system reports two assignment patterns for the same IL offset we'll treat them as the same assignment operation (and merge the values as per the recent multi-method scanning). This causes problems if there are two out parameters for the same callsite: [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
static Type _publicMethodsField;
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)]
static Type _publicPropertiesField;
static void TwoOutRefs(
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
out Type publicMethods,
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)]
out Type publicProperties)
{
publicMethods = null;
publicProperties = null;
}
public static void Test()
{
// IL2069 since we think the value from publicMethods parameter is assigned to _publicPropertiesField
TwoOutRefs (out _publicMethodsField, out _publicPropertiesField);
} Out (and ref) parameters get assignments after each method call (source value if the parameter value of the called method). In this both assignments will have the same Origin (the same callsite) and thus will be merged. If the annotations between the two parameters don't match this will produce warnings.
|
This also applies to NativeAOT. |
Currently we track each assignment pattern based on its Origin - which really means method + IL offset. So if the system reports two assignment patterns for the same IL offset we'll treat them as the same assignment operation (and merge the values as per the recent multi-method scanning). This causes problems if there are two out parameters for the same callsite:
Out (and ref) parameters get assignments after each method call (source value if the parameter value of the called method). In this both assignments will have the same Origin (the same callsite) and thus will be merged. If the annotations between the two parameters don't match this will produce warnings.
The text was updated successfully, but these errors were encountered: