Skip to content
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

Preserve static type info for return value of ctor #101212

Merged
merged 10 commits into from
Apr 30, 2024
Merged

Conversation

sbomer
Copy link
Member

@sbomer sbomer commented Apr 17, 2024

Fixes #101102.

Instead of tracking the return value as "unknown", this models the constructor as returning a value with a static type, letting us undo the workaround from #101031.

@sbomer sbomer requested a review from jtschuster April 17, 2024 21:22
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomer sbomer added area-Tools-ILLink .NET linker development as well as trimming analyzers and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Apr 17, 2024
@jtschuster
Copy link
Member

With these changes, are we able to remove the isNewObj check in MethodBodyScanner in the trimmer and ilc?

// Handle the return value or newobj result
if (!handledFunction) {
if (isNewObj) {
if (newObjValue == null)
methodReturnValue = new MultiValue (UnknownValue.Instance);
else
methodReturnValue = newObjValue;
} else {
if (!calledMethod.ReturnsVoid ()) {
methodReturnValue = UnknownValue.Instance;
}
}
}

// Handle the return value or newobj result
if (!handledFunction)
{
if (isNewObj)
{
if (newObjValue == null)
methodReturnValue = UnknownValue.Instance;
else
methodReturnValue = newObjValue;
}
else
{
if (!calledMethod.Signature.ReturnType.IsVoid)
{
methodReturnValue = UnknownValue.Instance;
}
}
}

Copy link
Contributor

Tagging subscribers to this area: @agocke, @sbomer, @vitek-karas
See info in area-owners.md if you want to be subscribed.

@sbomer
Copy link
Member Author

sbomer commented Apr 17, 2024

On the linker side I'm seeing some cases where handledFunction could potentially be false for a call to a ctor. Maybe it could be cleaned up, but I wouldn't do it as part of this change. @MichalStrehovsky any opinion on that?

Copy link
Member

@jtschuster jtschuster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming you tested it on the code that caused the original issue, LGTM.

@MichalStrehovsky
Copy link
Member

With these changes, are we able to remove the isNewObj check in MethodBodyScanner in the trimmer and ilc?

If we want to remove that, I'd remove the whole handledFunction part and the bool return value that feeds it and require the method to handle it always.

We have too many codepaths that try to manufacture a default return value. There's the one this PR is changing on line 1170 of HandleCallAction, but we also have these:

// If we get here, we handled this as an intrinsic. As a convenience, if the code above
// didn't set the return value (and the method has a return value), we will set it to be an
// unknown value with the return type of the method.
bool returnsVoid = calledMethod.Signature.ReturnType.IsVoid;
methodReturnValue = maybeMethodReturnValue ?? (returnsVoid ?
MultiValueLattice.Top :
annotatedMethodReturnValue);

// If we get here, we handled this as an intrinsic. As a convenience, if the code above
// didn't set the return value (and the method has a return value), we will set it to be an
// unknown value with the return type of the method.
bool returnsVoid = calledMethod.ReturnsVoid ();
methodReturnValue = maybeMethodReturnValue ?? (returnsVoid ?
MultiValueLattice.Top :
annotatedMethodReturnValue);

I wonder if we should change those too.

Ideally there would only be one place that manufactures these and not 3.

This place has the most context to do the right thing though (it is the place where we see it's a constructor, and the instruction was newobj - we lose the newobj information in the other spots).

@sbomer sbomer merged commit 30b3721 into dotnet:main Apr 30, 2024
109 of 113 checks passed
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
Instead of tracking the return value as "TopValue" or "unknown",
this models the constructor as returning a value with a static
type when called with newobj, letting us undo the workaround from
dotnet#101031.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
Instead of tracking the return value as "TopValue" or "unknown",
this models the constructor as returning a value with a static
type when called with newobj, letting us undo the workaround from
dotnet#101031.
@github-actions github-actions bot locked and limited conversation to collaborators May 31, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Tools-ILLink .NET linker development as well as trimming analyzers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dataflow analysis models result of newobj as MultiValueLattice.Top
4 participants