- Notifications
You must be signed in to change notification settings - Fork 7.6k
Improve variable type inference#19830
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
Conversation
ghost commented Jun 28, 2023
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
This PR has Quantification details
Why proper sizing of changes mattersOptimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
This PR has Quantification details
Why proper sizing of changes mattersOptimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
@MartinGC94 Is it possible to split the PR to some small ones? This would significantly speed up the review. |
Not in a meaningful way. It's a new Ast visitor so we kinda need the whole thing for it to make sense. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs Outdated Show resolvedHide resolved
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Co-authored-by: Ilya <darpa@yandex.ru>
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs Outdated Show resolvedHide resolved
Co-authored-by: Ilya <darpa@yandex.ru>
src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs Outdated Show resolvedHide resolved
src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs Outdated Show resolvedHide resolved
// The condition itself may not be interesting if it's after the cursor, but the statement block could be. | ||
return ast is PipelineBaseAst && ast.Parent is DoUntilStatementAst or DoWhileStatementAst | ||
? AstVisitAction.SkipChildren | ||
: AstVisitAction.StopVisit; |
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 wonder why not use VisitDoWhileStatement/VisitDoUntilStatement method directly? It would be more clear.
If SkipChildren is for condition - it is clear that we skip it, what is StopVisit for?
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.
It's not possible to do it from those methods because we can only tell it to continue, skip children, or stop completely. We want to skip the condition part of the loop (if it's after the variable being inferred) but we still want to process the body.
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.
My idea is that if we come in the methods we can return StopVisit but before directly call VisitStatementBlock for StatementBlockAst from Body.
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.
That doesn't work either. When calling VisitStatementBlock it will hit DefaultVisit which would return "Continue". Then it'd move on to the condition and hit the DefaultVisit again, and this time it will return "StopVisit" because it's after the cursor.
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.
Then it'd move on to the condition
If we run for Body
it cannot move to Condition
.
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 tried it on a local build and it behaved the way I described.
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.
After further thought, I believe I can take this as a step forward. Although I am inclined to believe that a direct bypass would be more convenient, simple and extensible. I'm even inclined to think that this was originally intended.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
It 'Ignores type constraint defined outside of scope' { | ||
$res = [AstTypeInference]::InferTypeOf(({ | ||
function Outer | ||
{ | ||
[string] $Test = "Hello" | ||
function Inner | ||
{ | ||
$Test = 2 | ||
$Test | ||
} | ||
} | ||
}.Ast.FindAll({param($Ast) $Ast -is [Language.VariableExpressionAst]}, $true) | Select-Object -Last 1 )) | ||
$res.Name | Should -Be 'System.Int32' | ||
} |
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.
Will the inference work after follow swap?
It 'Ignores type constraint defined outside of scope' { $res =[AstTypeInference]::InferTypeOf(({function Outer { function Inner { $Test =2 $Test }[string] $Test="Hello" Inner } ... $res.Name|Should-Be 'System.Int32' }
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.
Yes, $Test
inside the Inner
function will also be inferred as an int32 in this scenario because there's an assignment inside Inner
so outer scope type constraints/assignments don't matter.
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.
And if we remove $Test = 2
the inference will stop?
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.
Yes. It would stop the search before it would reach the assignment because it's after the start of the Inner
scope. This is not accurate to how PowerShell works, but trying to keep track of the variable values before each command invocation is quite difficult.
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.
Thanks! For idea, we would need a safe interpreter
.
@iSazonov Thanks for the approval. Is the plan to wait for MS to review it as well? |
@MartinGC94 I need a time to check all before merge. (Remind me in a couple of days if you don't see my activity.) |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
📣 Hey @MartinGC94, how did we do? We would love to hear your feedback with the link below! 🗣️ 🔗 https://aka.ms/PSRepoFeedback |
PR Summary
Improves the type inference of variables in the following ways:
[System.Management.Automation.Language.Parser]::ParseFile("ls", [ref] $Tokens, [ref] $null)
New-Guid -WarningVariable MyVar
[AstTypeInference]::InferTypeOf({$Global:true}.Ast)
[ValidateNotNull()]$Var1 = "Hello"
[int] [string] $Var1 = "10"
New-Guid 1>variable:RedirectedVar; $RedirectedVar
PR Context
Fixes#18759
Fixes#24205
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.(which runs in a different PS Host).