Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas
, '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

Union subtype reduction - #4537

Merged
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction
Aug 29, 2015
Merged

Union subtype reduction#4537
Mohamed Hegazy (mhegazy) merged 4 commits into
masterfrom
unionSubtypeReduction

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR rolls back some of the changes related to union types introduced in #3823. Specifically, we now again use subtype reduction as the primary means of removing redundant constituent types in union types. This improves backwards compatibility without impacting the strict object literal assignment checking that was the primary purpose of #3823.

It turns out that subtype reduction isn't at odds with strict object literal assignment checks as long as we are a bit more selective about where we perform the reduction. Specifically, because fresh object literals are subtypes only of object types with an exact matching set of properties (the fresh object literals can have neither too many nor too few properties), we get pretty much the same behavior from subtype checks as we did from the new deduplication algorithm in #3823.

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Jason Freeman (@JsonFreeman) Thought this might interest you!

Choose a reason for hiding this comment

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

Perhaps isExpectedProperty would better describe this.

@JsonFreeman

Copy link
Copy Markdown
Contributor

Whoa, interesting! That's true about fresh object literals failing the subtype test for subtype reduction. I have two general questions:

  1. Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?
  2. What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

@mhegazy

Copy link
Copy Markdown
Contributor

👍

Comment threadsrc/compiler/checker.ts Outdated

Choose a reason for hiding this comment

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

Use let

@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

Is there any concrete benefit to having subtype reduction (given the new way of computing signatures of union types), or is it just for simplicity - to avoid having an extra type relation?

It's mostly a backwards compatibility thing. We've seen several examples of real world code that was broken by the new behavior. The breaks all had to do with call signatures disappearing because a union type didn't get reduced to a single supertype. Of course it doesn't hurt that this new (or perhaps I should say old) way of doing things is also simpler in that there isn't a new kind of type relationship we have to document and reason about.

What is the difference between this incarnation of subtype reduction and the way it used to be? Presumably this fact about fresh object literals not getting thrown away would have applied before as well.

Consider this example:

vara=[{x: 1},{x: 2,y: 2}];// ({ x: number } | { x: number, y: number })[]

Because the elements have fresh object literal types they aren't subtypes of each other, so the element type of the array literal is a union type. As we widen the type of the array literal we make sure _not_ to perform subtype reduction again as that would collapse the union when the object literal types lose their freshness. So, the full type survives as the type of a and the array literal is assignable to a. That previously wasn't the case (at one point in the evolution of #3823 we were in a state where the above was an error), and that's really the big difference.

Mohamed Hegazy (mhegazy) added a commit that referenced this pull request Aug 29, 2015
@mhegazy
Mohamed Hegazy (mhegazy) deleted the unionSubtypeReduction branch August 29, 2015 00:48
@JsonFreeman

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Got it. Thanks for the explanation! So the difference is that noSubtypeReduction is true for the call to getUnionType in getWidenedType? That would seem to be the trap where subtype reduction is dangerous.

The scheme of aggregating the signatures of a union type is remaining as is, correct? I think it's still good for union types that didn't collapse under subtype reduction.

@microsoftMicrosoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@ahejlsberg@JsonFreeman@mhegazy@DanielRosenwasser@msftclas