Title: @() (array-subexpression operator) should not be optimized away when a cast to an array type is involved · Issue #4280 · PowerShell/PowerShell · GitHub
Open Graph Title: @() (array-subexpression operator) should not be optimized away when a cast to an array type is involved · Issue #4280 · PowerShell/PowerShell
X Title: @() (array-subexpression operator) should not be optimized away when a cast to an array type is involved · Issue #4280 · PowerShell/PowerShell
Description: This is a follow-up to the discussion involving @daxian-dbw and @PetSerAl in #4257 Context: PSv5.1 introduced a generally helpful optimization that optimizes @() away in cases where an array is directly constructed inside of it. I presum...
Open Graph Description: This is a follow-up to the discussion involving @daxian-dbw and @PetSerAl in #4257 Context: PSv5.1 introduced a generally helpful optimization that optimizes @() away in cases where an array is dir...
X Description: This is a follow-up to the discussion involving @daxian-dbw and @PetSerAl in #4257 Context: PSv5.1 introduced a generally helpful optimization that optimizes @() away in cases where an array is dir...
Opengraph URL: https://github.com/PowerShell/PowerShell/issues/4280
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"@() (array-subexpression operator) should not be optimized away when a cast to an array type is involved","articleBody":"\u003csup\u003eThis is a follow-up to the discussion involving @daxian-dbw and @PetSerAl in #4257\u003c/sup\u003e\r\n\r\nContext:\r\n\r\n* PSv5.1 introduced a generally helpful optimization that optimizes `@()` away in cases where an array is _directly_ constructed inside of it.\r\n * I presume that the motivation for this optimization was the widespread, but redundant and inefficient practice of enclosing `,`-constructed arrays (\"array literals\") in `@()`, such as in `@(1, 2)`, where `1, 2` would not only suffice, but, in PSv5-, `@()` would actually (effectively) _clone_ the array.\r\n\r\n* **Unfortunately, this optimization is also applied when a _cast_ to an array type (e.g, `[int[]]`) is involved, which can have unpleasant side effects** - see below. \r\n_Not_ optimizing in this scenario makes for conceptually clearer, predictable behavior.\r\n\r\n* While a change would technically be a breaking one, it is hard to imagine anyone having relied on the optimized behavior _with casts_ - a typical [Bucket 3: Unlikely Grey Area](https://github.com/PowerShell/PowerShell/blob/master/docs/dev-process/breaking-change-contract.md#bucket-3-unlikely-grey-area) change.\r\n\r\n * Also note that when the optimization was _introduced_ in PSv5.1, it was technically a breaking change too - though I suspect it wasn't announced as such or even at all.\r\n\r\nSteps to reproduce\r\n------------------\r\n\r\n```powershell\r\n@([int[]] (1, 2)).GetType().Name\r\n\r\n$arr = 1, 2; @([int[]] $arr).GetType().Name\r\n```\r\n\r\nExpected behavior\r\n-----------------\r\n\r\n```none\r\nObject[]\r\nObject[]\r\n```\r\n\r\nActual behavior\r\n---------------\r\n\r\n```none\r\nInt32[]\r\nInt32[]\r\n```\r\n\r\nNote that versions up to and including v5 - before the optimization was introduced - behave as expected.\r\n\r\nWhy is the current behavior problematic?\r\n-----------------------------------------\r\n\r\n\u003csup\u003eThe examples in this section are courtesy of @PetSerAl.\u003c/sup\u003e\r\n\r\nAll examples are undoubtedly edge cases, but the larger point is that this behavior should never have been introduced, and, given its \"stealth status\", this is an opportunity to get rid of it.\r\n\r\n* It subverts the fundamental assumption that `@()` always creates regular PowerShell arrays (`System.Object[]`):\r\n\r\n```powershell\r\n\u003e @([int[]] (1, 2))[-1] = 'foo' # BREAKS, because the array is [int[]], not [object[]]\r\nCannot convert value \"foo\" to type \"System.Int32\". ...\r\n...\r\n```\r\n\r\n@PetSerAl points out that this fundamental assumption is even still reflected in other places in the source code: [`ArrayExpressionAst.StaticType`](https://github.com/PowerShell/PowerShell/blob/master@%7B2017-07-18%7D/src/System.Management.Automation/engine/parser/ast.cs#L9490) (a `@(...)` expression is of type `[System.Management.Automation.Language.ArrayExpressionAst]`).\r\n\r\n* It subverts the expectation that `@()` always _clones_ an array:\r\n\r\n```powershell\r\n\u003e $a = [int[]] (1, 2); $b = @([int[]] $a); [object]::ReferenceEquals($a, $b)\r\nTrue # $a and $b unexpectedly reference the same array.\r\n```\r\n\r\nNote that the accidental reference equality only happens ~if the source type and the cast type are identical~ if the cast type is either the same as the source type or a type that the source type is (directly or indirectly) derived from (covariance).\r\n\r\nThus, if the _cast_ type is `[object[]]` and the source type is a reference type too, the problem always surfaces.\r\n\r\nEnvironment data\r\n----------------\r\n\r\n```powershell\r\nPowerShell Core v6.0.0-beta.4 on macOS 10.12.5\r\nPowerShell Core v6.0.0-beta.4 on Ubuntu 16.04.2 LTS\r\nPowerShell Core v6.0.0-beta.4 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)\r\nWindows PowerShell v5.1.15063.413 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)\r\n```\r\n","author":{"url":"https://github.com/mklement0","@type":"Person","name":"mklement0"},"datePublished":"2017-07-18T14:27:02.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":31},"url":"https://github.com/4280/PowerShell/issues/4280"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:872eb8e9-3b77-7e73-df4e-6b80e03f3e52 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | EA0C:206F37:66A134:89C459:6A5B5E94 |
| html-safe-nonce | d4c196ce44aac49c6da1bd6dee7fe867718581d4aba3037c4bf66c61d9409718 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFQTBDOjIwNkYzNzo2NkExMzQ6ODlDNDU5OjZBNUI1RTk0IiwidmlzaXRvcl9pZCI6IjU1MDc0Njk0MjE5NDQ5ODcyODQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | fb1a3c653d7a0b5888ebd2f80b4777e3cd3e871a78429adca95085ca9b53a2fa |
| hovercard-subject-tag | issue:243735465 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/PowerShell/PowerShell/4280/issue_layout |
| twitter:image | https://opengraph.githubassets.com/5a4e37686b532bc4232433f226a8989019b2f3a068cacf2fe8fe1417b1c76d67/PowerShell/PowerShell/issues/4280 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/5a4e37686b532bc4232433f226a8989019b2f3a068cacf2fe8fe1417b1c76d67/PowerShell/PowerShell/issues/4280 |
| og:image:alt | This is a follow-up to the discussion involving @daxian-dbw and @PetSerAl in #4257 Context: PSv5.1 introduced a generally helpful optimization that optimizes @() away in cases where an array is dir... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | mklement0 |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5290d7e14309ad1e76106a9c4237bd1041517e83ea182c8ab756752cb0c6940b |
| turbo-cache-control | no-preview |
| go-import | github.com/PowerShell/PowerShell git https://github.com/PowerShell/PowerShell.git |
| octolytics-dimension-user_id | 11524380 |
| octolytics-dimension-user_login | PowerShell |
| octolytics-dimension-repository_id | 49609581 |
| octolytics-dimension-repository_nwo | PowerShell/PowerShell |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 49609581 |
| octolytics-dimension-repository_network_root_nwo | PowerShell/PowerShell |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 9c975978430e9ad293956f2bbdaf153b1bd84a99 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width