GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix array expression to not return null or throw error by daxian-dbw · Pull Request #4296 · PowerShell/PowerShell

Conversation

@daxian-dbw

@daxian-dbw Dongbo Wang (daxian-dbw) commented Jul 19, 2017 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Fix #4280

Summary

This PR focuses on 3 issues:

  1. According to PowerShell Language Specification Version 3.0, as quoted: "The result is the (possibly empty) unconstrained 1-dimensional array", @(...) should only return object[] array.
  2. @([object[]]$null).GetType() fails with error "You cannot call a method on a null-valued expression."
  3. @([System.Collections.Generic.List[object]]$null) fails with error "Object reference not set to an instance of an object."

Marked with label Review-Committee to review the first issue.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Dongbo Wang (daxian-dbw) added 3 commits July 19, 2017 11:42
@daxian-dbw
Fix array expression to not return null or throw error
e987ef1
@daxian-dbw
Update tests
be0a266
@daxian-dbw
Add '-Tags CI'
50b55cd
@daxian-dbw Dongbo Wang (daxian-dbw) added the Review - Committee The PR/Issue needs a review from the PowerShell Committee label Jul 19, 2017
@daxian-dbw Dongbo Wang (daxian-dbw) self-assigned this Jul 19, 2017
@daxian-dbw
Dongbo Wang (daxian-dbw) requested a review from Jason Shirk (lzybkr) July 19, 2017 19:11
@msftclas Microsoft Contribution License Agreements (msftclas) added the cla-not-required label Jul 19, 2017
@daxian-dbw Dongbo Wang (daxian-dbw) changed the title Array Fix array expression to not return null or throw error Jul 19, 2017
@daxian-dbw
Update tests again
bdbe68d
iSazonov
Ilya (iSazonov) reviewed Jul 20, 2017
View reviewed changes
Comment thread test/powershell/Language/Scripting/Array.Tests.ps1
It "@([object[]](1,2,3)) should return a 3-element array of object[]" {
$result = @([object[]](1,2,3))
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 3

@iSazonov Ilya (iSazonov) Jul 20, 2017

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I believe we should check $result.Length before $result.GetType() in all test here. This is not important in these tests, but it is a bad pattern for other tests in which the $result are calculated. (I mean that somebody can copy-paste the bad pattern).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 20, 2017

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

What do you mean by the $result are calculated? Can you please elaborate a bit and give an example?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iSazonov Ilya (iSazonov) Jul 20, 2017

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

From Get-Content.Tests.ps1:

  It "should Get-Content with a variety of -Tail and -ReadCount values" {#[DRT]
    set-content -path $testPath "Hello,World","Hello2,World2","Hello3,World3","Hello4,World4"
    $result=get-content -path $testPath -readcount:-1 -tail 5
    $result.Length | Should Be 4

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iSazonov Ilya (iSazonov) Jul 20, 2017

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Can we use Should BeOfType?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 20, 2017

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

To use Should BeOfType I need to wrap $result in a new array because it will be unraveled otherwise. I feel it's clearer to just use GetType().FullName in this case.

As for the bad pattern, I'm still confused. Why do you think putting $result.Length | Should Be 3 after the type check would be a bad pattern? More technically speaking, the length check should happen after we know $result is an array, otherwise we might (actually impossible) end up checking the Length property of some random type :)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

iSazonov reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@iSazonov Ilya (iSazonov) Jul 20, 2017

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

 function foo {$null}
 $res = foo
 $res.GetType()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $res.GetType()
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 20, 2017

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Ah, I see your point. A Should Not BeNullOrEmpty check should be done in that case.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

iSazonov reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
Comment thread test/powershell/Language/Scripting/Array.Tests.ps1
}

It "@([int[]](1,2,3)) should return a 3-element array of object[]" {
$result = @([int[]](1,2,3))

@iSazonov Ilya (iSazonov) Jul 20, 2017

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Should we test complex types? PSCustomObject?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 20, 2017

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

For any array type other than [object[]], it will fall in the code path of PSToObjectArrayBinder. I just use [int[]] as a simple validation.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iSazonov Ilya (iSazonov) Jul 20, 2017

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Sorry, I mean member types.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 20, 2017

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Oh, the member type doesn't matter for the scenario of this fix. It's OK as long as the conversion works.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

iSazonov reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@iSazonov

Ilya (iSazonov) commented Jul 20, 2017

Copy link
Copy Markdown
Collaborator

Should we add tests for @($var) ? It seems absent.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

lzybkr
Jason Shirk (lzybkr) reviewed Jul 24, 2017
View reviewed changes
Comment thread src/System.Management.Automation/engine/parser/Compiler.cs Outdated
values = values ?? CaptureAstResults(subExpr, CaptureAstContext.Enumerable);

if (values.Type.IsArray)
if (values.Type == typeof(object[]) || values.Type == typeof(List<object>))

@lzybkr Jason Shirk (lzybkr) Jul 24, 2017 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

The goal of the optimization was to cover @(1,2) - so maybe the original test was too general. This fix ends up adding unnecessary overhead to the optimization by cloning and adding an if test.

I think a better fix is to just constrain the optimization more - basically if (subExpr is ArrayLiteralAst).

I don't recall why I added the List<object> case.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 24, 2017 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

The clone was added to address a comment raised by PetSerAl about $a = 1,2,3; @([object[]]$a) doesn't return a new array. But if we only consider if (pureExpr is ArrayLiteralAst) then the clone and the null check are both not necessary anymore.

The List<object> case seems like an optimization for CaptureAstResults, because a List<object> instance will be created to hold the objects written to pipe in CaptureAstResults.
Are you suggesting to not cover the cases of values.Type == typeof(object[]) and values.Type == typeof(List<object>) here?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@daxian-dbw Dongbo Wang (daxian-dbw) Jul 24, 2017

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Replace the cases of values.Type.IsArray and values.Type == typeof(List<object>) with if (pureExprAst is ArrayLiteralAst). So the former cases will be handled by the dynamic site.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Dongbo Wang (daxian-dbw) added 2 commits July 24, 2017 15:56
@daxian-dbw
Address comment
33b5461
@daxian-dbw
Add 2 more tests
88a68ab
lzybkr
Jason Shirk (lzybkr) approved these changes Jul 25, 2017
View reviewed changes

@lzybkr Jason Shirk (lzybkr) left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I think the change is fine.

I should add that the intent of @() is not to create a new array, but to ensure the result is an array, and not necessarily an object[].

In other words, I think we could be open to changing what the language specification says to allow for better performance.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@daxian-dbw
Change 2 tests
237c2bb
@daxian-dbw

Dongbo Wang (daxian-dbw) commented Jul 25, 2017

Copy link
Copy Markdown
Member Author

the intent of @() is not to create a new array, but to ensure the result is an array

The last commit removed the [object]::ReferenceEquals check from the test per Jason's comment.
But the check for System.Object[] is kept as we haven't changed the language specification yet.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@daxian-dbw
Add a test about @([System.Collections.Generic.List[object]]$null)
ce4d2d9
@daxian-dbw
Dongbo Wang (daxian-dbw) merged commit 0d8eff6 into PowerShell:master Jul 25, 2017
@daxian-dbw
Dongbo Wang (daxian-dbw) deleted the array branch July 25, 2017 04:52
@daxian-dbw Dongbo Wang (daxian-dbw) mentioned this pull request Aug 4, 2017
@() (array-subexpression operator) should not be optimized away when a cast to an array type is involved #4280
Closed
@SteveL-MSFT Steve Lee (SteveL-MSFT) removed the Review - Committee The PR/Issue needs a review from the PowerShell Committee label Aug 16, 2018
@shuangxue520 liushuang (shuangxue520) mentioned this pull request Jul 12, 2026
Array subexpression @($list) throws "Argument types do not match" for List[object] created by New-Object #27558
Open
Thatgfsj (Thatgfsj) pushed a commit to Thatgfsj-contribs/PowerShell that referenced this pull request Aug 6, 2026
@daxian-dbw
Fix array expression to not return null or throw error (PowerShell#4296)
4193685
This change fixes 3 issues:
- According to [PowerShell Language Specification Version 3.0](https://www.microsoft.com/en-us/download/details.aspx?id=36389), as quoted: "_The result is the (possibly empty) unconstrained 1-dimensional array_", `@(...)` should only return `object[]` array.
- `@([object[]]$null).GetType()` fails with error `"You cannot call a method on a null-valued expression."`
- `@([System.Collections.Generic.List[object]]$null)` fails with error `"Object reference not set to an instance of an object."`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@iSazonov Ilya (iSazonov) iSazonov left review comments
+1 more reviewer
@lzybkr Jason Shirk (lzybkr) lzybkr approved these changes
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@daxian-dbw Dongbo Wang (daxian-dbw)

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@daxian-dbw @iSazonov @lzybkr @msftclas @SteveL-MSFT
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.