Class broken when containing file is updated (Cannot convert the "ReproType" value of type "ReproType" to type "ReproType")
See original GitHub issueJust like re-executing Add-Type
for a snippet of C# code that has not changed, reloading a module that uses classes should also continue to work–even if a script file that contains the [unmodified] class has changed.
(I felt this problem was covered by #14250, but the owner closed it, and this problem is still irritating us, to the point we might just rip out all usage of PowerShell classes.)
This does not only come up during development scenarios. For example, I have a module that auto-updates itself, and then instructs the end user to run “Import-Module [...] -Force
” to pick up the changes. (And then I get complaints from users when the module breaks in a really nonsensical-looking way.)
The key to the repro below is touching the file where the class is defined (before re-importing the module). You don’t have to change the class definition; just add some whitespace somewhere else in the file. Which makes me think that the logic out there for deciding whether to generate a new runtime type for the class is making its decision based on whether the containing file has changed or not, but could do better by looking at just the extent where the class is defined.
Steps to reproduce
mkdir Repro_gh_14250 | Out-Null
pushd Repro_gh_14250
New-ModuleManifest -Path .\Repro.psd1 -RootModule Repro.psm1
@'
$script:data = [ordered] @{
First = @("Primo", 123)
Second = @("Secundo", 456)
}
class ReproType
{
[string] $Name
[int] $Number
}
$TheList = @()
foreach( $key in $script:data.Keys )
{
$newThing = [ReproType]::new()
$newThing.Name = $script:data[ $key ][ 0 ]
$newThing.Number = $script:data[ $key ][ 1 ]
$TheList += $newThing
}
function Get-TheList
{
[CmdletBinding()]
param()
process { return $TheList }
}
'@ > Stuff1.ps1
@'
function Show-TheList
{
[CmdletBinding()]
param( [ReproType[]] $TheItems )
process
{
foreach( $item in $TheItems )
{
Write-Host $item.Name -Fore Cyan -NoNewline
Write-Host ": " -NoNewline
Write-Host $item.Number -Fore Yellow
}
}
}
function Repro
{
[CmdletBinding()]
param()
$stuff = @( Get-TheList )
Show-TheList $stuff
}
'@ > Stuff2.ps1
@'
. "$PSScriptRoot\Stuff1.ps1"
. "$PSScriptRoot\Stuff2.ps1"
'@ > Repro.psm1
ipmo .\Repro.psd1 -Force
Repro
'# nothing' >> .\Stuff1.ps1
ipmo .\Repro.psd1 -Force
Repro # EXPECTED: it works. ACTUAL: Cannot process argument transformation on parameter 'TheItems'. Cannot convert the "ReproType" value of type "ReproType" to type "ReproType".
Expected behavior
No problems after reloading the module.
Actual behavior
After reloading the module, I get errors when using the [unmodified] class:
Cannot process argument transformation on parameter 'TheItems'. Cannot convert the "ReproType" value of type "ReproType" to type "ReproType"
Environment data
Name Value
---- -----
PSVersion 7.2.0-preview.3
PSEdition Core
GitCommitId 7.2.0-preview.3
OS Microsoft Windows 10.0.20293
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:6 (3 by maintainers)
Top GitHub Comments
Ahh I see, this is different from the issue you linked as none of it is exposed outside the module. Type is probably cached in the AST and not correctly invalidated. Outside of function signatures (parameter types, attributes, etc) it’ll work with forced reloads though.
I went ahead and hid my other comments as outdated, thanks for the correction.
Sorry, I don’t mean to be obtuse, but: the point of this Issue is that they demonstrably do NOT work when reloaded (see the repro steps). I am not sure where our miscommunication is… can you please clarify?