PS D:\> New-Item 7n
(and current behavior in PS 6)
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 1/18/2020 1:24 PM 0 7n
A file with an unexpected name is created.
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 1/18/2020 1:24 PM 0 7
Name Value
---- -----
PSVersion 7.0.0-rc.2
PSEdition Core
GitCommitId 7.0.0-rc.2
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
When the other numeric types are used as an argument, PS wraps them inside a [psobject]
if their numeric and string representations differ so that PS can extract the original string if needed later (e.g. if it's bound to a [string[]]
parameter as with New-Item
above.) Thus New-Item 7ul
works as expected, but New-Item 7n
does not.
I'm sorry but I don't know how/where this happens in the code though....
Mentioning @vexx32 because I believe they created the BigInt type-suffix support (thanks!).
That's a good point. I'm not sure _where_ this handling happens. Perhaps @SeeminglyScience could point us in the right direction?
Inferring from the fact that 7ul
works correctly (which is _also_ a new addition), the fact that 7n
does not seems to indicate that whatever the parameter binder(?) is looking for is likely a static set of types, or perhaps just numeric values. It probably doesn't consider BigInteger numeric since it's not a primitive but rather a struct. 馃
When a numeric literal is sent to a command, it's wrapped in a PSObject
with it's internal TokenText
property set to the original string determined at parse time.
This isn't happening for big int literals, the TokenText
property is null. There's a few reasons that could be happening, the check to see if the argument should be wrapped is done here:
So one of those checks (probably the IsNumeric
check since bigint's type code is Object
) needs to be tweaked.
Interesting, thank you! 馃槉
So... hm.. Either we'd have to add an additional piece of logic to special case for the BigInteger case... or we'd have to alter the type code information so it reads it as numeric. It _seems_ like the latter would be the better move, but that's only if that's feasible.
I'm not really sure how the type code stuff works; is that built into .NET or something handled in LanguagePrimitives? I remember seeing stuff related to it in there, but I'm not sure if that's something we can change from the PowerShell side of things? 馃
I added new condition to pass line 4177 and it is not full fix.
@iSazonov I changed it to:
if (constElement != null
&& (LanguagePrimitives.IsNumeric(LanguagePrimitives.GetTypeCode(constElement.StaticType))
|| constElement.StaticType == typeof(System.Numerics.BigInteger)))
and Write-Host 7n
wrote 7n
.
My tests:
Select-String -InputObject 7n -Pattern 7n
# and
New-Item 7n
Looks like we need to add another test case for functions. Cmdlets seem to work with that change, but there's something else that needs to happen, it seems...
function Test-StringLiteral {
param([string]$Value)
$Value
}
# ...
PS> Test-StringLiteral -Value 7n
7
This appears to still be problematic for both simple and advanced functions.
EDIT: I found another reference to the IsNumeric()
method that seems relevant here:
https://github.com/PowerShell/PowerShell/blob/d58a82ad19fbfad81e85778c8b08cb1b28f58fce/src/System.Management.Automation/engine/runtime/ScriptBlockToPowerShell.cs#L649-L660
However, even with that changed similarly to the above suggestions, I'm still not seeing script functions behave correctly with BigInteger, while they will behave perfectly well with other suffixed numerals. Time to do some more digging!!
Aaaand one further update -- adding BigInteger to the array of s_numericTypes
in LanguagePrimitives
seems to completely sort this out, for simple & advanced functions and all! 馃帀
Will PR a thorough fix shortly! Thanks for the pointers, everyone! 馃挅 馃槉
:tada:This issue was addressed in #11634, which has now been successfully released as v7.1.0-preview.3
.:tada:
Handy links:
Most helpful comment
When a numeric literal is sent to a command, it's wrapped in a
PSObject
with it's internalTokenText
property set to the original string determined at parse time.This isn't happening for big int literals, the
TokenText
property is null. There's a few reasons that could be happening, the check to see if the argument should be wrapped is done here:https://github.com/PowerShell/PowerShell/blob/70d4a899310f5460700f0be8cba5a2af1d4a0305/src/System.Management.Automation/engine/parser/Compiler.cs#L4174-L4183
So one of those checks (probably the
IsNumeric
check since bigint's type code isObject
) needs to be tweaked.