Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Preserve static type info for return value of ctor - #101212

Merged
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal
Apr 30, 2024
Merged

Preserve static type info for return value of ctor#101212
sbomer merged 10 commits into
dotnet:mainfrom
sbomer:ctorRetVal

Conversation

@sbomer

Copy link
Copy Markdown
Member

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 jtschusterApril 17, 2024 21:22
@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 17, 2024
@sbomersbomer 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
Copy Markdown
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=newMultiValue(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;
}
}
}

@dotnet-policy-service

Copy link
Copy Markdown
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
Copy Markdown
MemberAuthor

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?

@jtschusterjtschuster left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
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.
boolreturnsVoid=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.
boolreturnsVoid=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).

Comment threadsrc/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs Outdated
@sbomer
sbomer merged commit 30b3721 into dotnet:mainApr 30, 2024
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-actionsgithub-actionsBot locked and limited conversation to collaborators May 31, 2024
@sbomer
sbomer deleted the ctorRetVal branch June 26, 2026 18:07
Sign up for freeto 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

@sbomer@jtschuster@MichalStrehovsky@vitek-karas