Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default case in Switch not called when variable is in an undefined state #21558

Open
5 tasks done
TheToor opened this issue Apr 30, 2024 · 6 comments
Open
5 tasks done
Assignees
Labels
Needs-Triage The issue is new and needs to be triaged by a work group. WG-Engine core PowerShell engine, interpreter, and runtime

Comments

@TheToor
Copy link

TheToor commented Apr 30, 2024

Prerequisites

Steps to reproduce

The following code gives no output:

$Test = $Null | Out-Null
switch($Test) {
  $null { Write-Host "It's null" }
  Default { Write-Host "It's Default" }
}

The following codes gives an output on the $null case:

$Test = $Null
switch($Test) {
  $null { Write-Host "It's null" }
  Default { Write-Host "It's Default" }
}

Expected behavior

Either the $null or Default case should be called

Actual behavior

Neither of the cases is called when the output of the pipeline is empty.
This is also reproducable with a custom function returning nothing:
`Function Out-CustomNull { return }`

Emits the same behaviour in the switch case above

Error details

No error

Environment data

Name                           Value
----                           -----
PSVersion                      7.4.2
PSEdition                      Core
GitCommitId                    7.4.2
OS                             Microsoft Windows 10.0.22631
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

@TheToor TheToor added the Needs-Triage The issue is new and needs to be triaged by a work group. label Apr 30, 2024
@mklement0
Copy link
Contributor

mklement0 commented Apr 30, 2024

$Null | Out-Null doesn't return $null; any cmdlet (or function / script file / script block) - such as Out-Null - that produces no output technically returns the [System.Management.Automation.Internal.AutomationNull]::Value singleton, the "enumerable null", if you will.

In an enumeration context - including input provided to a switch statement - [System.Management.Automation.Internal.AutomationNull]::Value behaves like an empty enumerable; that is, no iterations take place; the switch statement is effectively skipped.

That is, it behaves like the following statement: switch (@()) { Default { 'never get here' } }: enumerating the empty array results in no elements, so the statement body is never entered.

What is tricky is that it isn't easy to discover whether a given variable value is a bona fide $null or [System.Management.Automation.Internal.AutomationNull]::Value, especially given that in expression contexts as well as in parameter-binding, the latter is effectively the same as $null.

#13465 is a green-lit proposal to make discovery of [System.Management.Automation.Internal.AutomationNull]::Value easier, via $Test -is [System.Management.Automation.AutomationNull], but it hasn't been implemented yet; also, it was inappropriately closed by the bot.

@237dmitry
Copy link

237dmitry commented Apr 30, 2024

default is executed when no switches are found that match the condition.

$null -eq $null     # True

undefined state

$a = $null
Get-Variable a

@TheToor
Copy link
Author

TheToor commented Apr 30, 2024

@237dmitry
Default is not executed in that case. That is the problem.

$Test = $Null | Out-Null
switch($Test) {
  $null { Write-Host "It's null" }
  Default { Write-Host "It's Default" }
}

Produces no output when the default case should have been run.

@TheToor
Copy link
Author

TheToor commented Apr 30, 2024

Thanks @mklement0 for the detailed explaination.
Digging through the other proposal and issues this is probably a case not often encountered but still results in confusing behaviour when it happens.

Any plans to reopen the conversation of your proposed implementation?

@237dmitry
Copy link

237dmitry commented Apr 30, 2024

Default is not executed in that case. That is the problem.

This is because there is a $null switch, which is equivalent to $Test and returns $true. If you have a match, then default will not be executed.

Look at full syntax:

 $ & {
         $test = $null
         switch ($test)
         {
            {$_ -eq 1}     { 1 }
            {$_ -eq 'one'} { 'one' }
            {$_ -eq $null} { 'null' }
            default { 'default' }
         }
    }
null

$

@mklement0
Copy link
Contributor

mklement0 commented Apr 30, 2024

Glad to hear it helped, @TheToor; I have no say in what gets reopened, but I generally think that all auto-closed issues that have the Up-for-Grabs label should be reopened, as previously suggested in #21406 (comment).

@StevenBucher98 StevenBucher98 added the WG-Engine core PowerShell engine, interpreter, and runtime label May 6, 2024
@daxian-dbw daxian-dbw self-assigned this May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs-Triage The issue is new and needs to be triaged by a work group. WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

No branches or pull requests

5 participants