Open cagyirey opened 7 years ago
@cagyirey Thank you for the bug report.
Do you want to try to fix it?
Hi @sergey-tihon
I'll certainly take a shot at it. I've gotten similar errors with a few other cmdlets, and I don't have a good solution for debugging the type provider yet. Trying to examine local variables (i.e. the state of the type inferrer when the provider loads) in the Visual Studio debugger gives me an Internal F# Compiler Error
. I might have to write a small tool for dumping cmdlet signatures unless you know anything about what I'm doing wrong in the debugger.
I've managed to learn a little more about the bug. line 134 in HostedRuntime.Execute is being triggered because - and this doesn't show up in the Get-ExecutionPolicy signature - listing the policies returns a collection of PSCustomObject
s consisting of a MachineScope
and the ExecutionPolicy
. Line 134 here makes a PSObject
out of that collection, but the type inferrer gets a List<ExecutionPolicy>
here on line 33 for the other overload (the only one that shows up in the PSCommandSignature list) to Get-ExecutionPolicy
. Line 138 ultimately ends up trying to construct a PSCmdletResult<List<ExecutionPolicy>, _>
out of a boxed Collection<PSObject>
because of the wrong ResultType
.
Apparently PowerShell populates CommandInfo.OutputType
from an attribute that goes on the cmdlet type. So there's no actual guarantee the output type will actually match the real output. It doesn't seem like there's a way to guess when it'll happen, otherwise a simple fix would be to infer PSObject
for those cmdlets and let the user unbox it.
Do not we have another tricky way to get all possible result type instead of exposing PSObject
to the user?
If there is another way, it might have to be a very clever fix. PS doesn't decide what kind of output you get until the last minute:
Not great for type inference. Because it's just 2 branches of the same function, you can't tell from the CommandInfo it does anything special. Besides looking at the disassembly, I haven't found any good indicators for which cmdlets do this.
Ok, here is the problem with this case and others like it. The Type Provider is inferring return types from the powershell OutputType documentation, however Microsoft says that "The OutputType attribute value is only a documentation note. It is not derived from the function code or compared to the actual function output. As such, the value might be inaccurate." as you can see in the following link: outputType docs.
In this particular case, you can see the informed return type: .
This means that the type provider will infer that this function will always return a ExecutionPolicy type, but in this case, the "list=true" parameter is changing the output type from ExecutionPoliciy to an Object[] and therefore produces this error.
One solution I can think of is to add a "default case type" to the inferred types in order to account for this behaviour. Since this type list is constructed when the type provider "reads" the types, I don't think we can change the return at runtime but another option would be to use a kind of dynamic type which would also be a design compromise (since we would lose the static typing).
Description
The type inference engine gives the wrong result type when trying to list
ExecutionPolicy
objects.Repro steps
getExecutionPolicy()
orgetLocalExecutionPolicy()
to observe the results.Expected behavior
The type inferer should not try to cast from a
PSObject
directly toList<ExecutionPolicy>
. Perhaps it's theBaseObject
that contains the execution policy list?Actual behavior
An exception with the message
Object of type 'System.Management.Automation.PSObject' cannot be converted to type 'Microsoft.FSharp.Collections.FSharpList1[Microsoft.PowerShell.ExecutionPolicy]'
is thrown.Related information
Repro