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
missing property reference error ignored if followed by unary operator #9564
Comments
I suppose the property reference is consuming the result of the unary operation? This is kind of unexpected, as I wouldn't expect it to accept such a result without something like parenthesis around it or something ... |
What seems to be happening is the PS ignores whitespace immediately after a property accessor. This case in the parser is meant to handle things like this: $ReallySillyLongName.PropertyOneThatIsLong.
MethodName() But it does seem to be a bug that if you follow it with whitespace and then a defined operator that it simply processes the property name with either just whitespace or possibly an empty string. This is because the hyphen that starts such an operator is actually a token-separating character and isn't usable as a property name character without encloding is in quotes. So it's trying to be lenient and helpful and ignore the space, but the subsequent breaking character leaves it with a whitespace-only property name -- which it presumably trims to an empty string -- which isn't a defined property name at all, so it gives back $null as you're not working in StrictMode. Then the split operation is actually applied, but it already has nothing to work with, and also returns $null. /cc @daxian-dbw seems like a parser bug where it forgets that this should be a parse error if the token is ended before it gets any characters to use for a property name? |
I was thinking maybe it was going to use the result of the -split unary operator as a member name, but I cannot seem to prove its doing that either. @{hello=3}. -split 'hello' # result is $null
@{hello=3}. 'hello' # result is 3 |
Yeah if the operator didn't need the hyphen it would. But since the hyphen is a character that effectively creates a token boundary it seems to end up with a null property name. Even this fails: PS> @{' -split "hello"' = "tricks"}. -split "hello"
# no result |
I also tried: @{hello=3}.(-split 'hello') # result is $null
@{hello=3}.('hello') # result is 3 |
If you leave off the operand for the split operator, the error message will imply that the operator was of the unary type, so its clearly looking for an expression, to which if the first term is an operator, it must be unary. |
This works: @{hello=3}.$(-split 'hello') # result is 3 |
@msftrncs you are right that it's using the unary expression as the member of the
The It's not that obvious, but the behavior should be by design. |
@daxian-dbw, I had gathered this so far, but it seems that this doesn't work as designed, because I provided further examples showing that it does not work, specifically with Examples: @{hello=3}.(-split 'hello') # result is $null
@{hello=3}.('hello') # result is 3
@{hello=3}.$(-split 'hello') # result is 3
@{hello=3}. -join 'hello' # result is 3 There seems to be something special going on with I also want to say that I think this is a bad design. It leads to confusion as to what later member accesses will actually be accessing. Of course, this is easy to clarify, by wrapping the expression in parenthesis, but I think the user/programmer should be forced to do that to disambiguate the reference. @{hello=3}. -join 'hello'.ToString() # result is [int]3
@{hello=3}.( -join 'hello').ToString() # result is [string]3 Above (first line), the Anyway, this is just my opinion. I do wonder, even without strict mode, if an error shouldn't be raised on certain inputs to the accessor member lookup. What good does an array object, or even numeric values, provide to an accessor member lookup? I have learned things from this at any rate.
This is important because I will use this information in PowerShell/EditorSyntax#156 to improve both the accessor syntax scoping and the general operation in expression mode. |
It's not PowerShell/src/System.Management.Automation/engine/runtime/Binding/Binders.cs Lines 1340 to 1351 in 0639133
The following would work:
The dynamic member accessing feature is very useful with a variable expression as the member, something like I do find a bug with indexing a Hashtable, see #9580 |
Yikes, I don't know why I didn't see this earlier, but hashtables accept any kind of object for a key (it seems). The EditorSyntax grammar doesn't recognize that. Since the key can contain the [string[]] object returned by
Little confusing why this doesn't work: @{-split 'hello'=4}. -split 'hello' Yet when you put it in a variable, and use the variable it does. That almost makes it look like its using the reference, and if the reference isn't the same, it doesn't work?? In the above, |
Well, those two |
I think the real crux of the confusion here is that this works without a subexpression operator, and as such there's no visible differentiator that would indicate that the operator is behaving as unary. In my own opinion, it would make more sense for this behaviour to require a subexpression operator to be used, and syntax error in all other cases where a member-access operator is followed by a unary operator. i.e., this should be fine, it's pretty clear what's happening:
Whereas this is only ever confusing in terms of what it's operating on, how it ought to behave, and what the result should ever be, if anything:
|
That's all fine and dandy … but the average user doesn't see it that way … the result is the same, and what makes it any more likely that two constants to follow those rules … that's why this stuff confuses us low level programmers... 'hello' = 'hello' because I compared every bit. obviously the difference is that [valuetype]'s do compare directly, but all others use their instance generated hashcodes for comparison. (actually [valuetype]s just generate the same hashcode when their bits match.) I can also understand the basis for dynamic member access … but if you cannot truly access certain members dynamically … whats the value? Of course from a processing standpoint, it makes for a simple rule. Originally I only thought there was a few things that was accepted, the unquoted non-expanding string, or a variable or a quoted string (I have been using all 3). I didn't realize it accepted an entire expression. And now I know there are some very big gotchas when that expression doesn't result in a [valuetype]. (and my reference to [valuetype] is probably not accurate, as strings are not [valuetype]) |
Is a conclusion "by design"? |
while it is surprising, I do think it is by design. |
Ok, until we get more UX negative feedback and I close with "By-Design" label. |
I found this by accident, left the
.
property reference while testing ideas.I think it is incorrect that this code goes without any errors, and also generates no result.
Steps to reproduce
Expected behavior
Actual behavior
Exactly, nothing happens, no error, no result. Any unary operator seems to do this. A non-unary operator will generate two error messages, missing property, and unexpected token (for the right operand).
Environment data
PowerShell 6.2 on Windows 10 1809
Windows PowerShell 5.1 (same OS)
The text was updated successfully, but these errors were encountered: