Question: Script file directive to select scope during import.

As a general rule, non-terminating errors tend to be something that comes from an individual object input in the pipeline. If one bad piece of data is received, you don't necessarily want to cancel processing the next 10,000 bits of input. On the other hand, if the error comes from bad / unusable input as the result of a fixed (non-pipeline) parameter input, you can deduce that processing all 10,000 bits of input will yield with the same result (say, for example, the cmldet requires authentication, and the authentication provider you're using indicates that the credentials specified are invalid) -- then you can throw a terminating error to avoid wasting time trying the known-bad credentials 10,000 times.

Script file directive to select scope during import.
### Prerequisites

- [X] I have written a descriptive issue title.
- [X] I have searched all issues to ensure it has not already been reported.

### Summary

A module provides a single "script" scope for the module that's shared even if the module spans multiple files. Non-module scripts do not have such a shared, non-global scope. Also, a script can be loaded into the current scope (dot sourced) or a new script scope (not dot sourced). The script might not be designed to work correctly with both load methods. There should be a means either to use the desired scope or to raise an error if loading into the incorrect scope.

### Proposed Design

Add an optional "#RequiresScope" directive to control the scope into which a file loads. A SCOPE parameter will, if required, override the scope that would be selected by the method of the load (dot sourced or not dot sourced). A FORCE directive parameter could control if the desired scope is always selected automatically or if an error is raised if the default scope does not match that required.

#RequiresScope Default - uses the either the current or script scope as if the directive was not present
#RequiresScope Global Force - uses the global scope when loaded
#RequiresScope Current Force - uses the current scope when loaded (always behaves as if dot sourced)
#RequiresScope Script Force - uses a new scope when loaded (always behaves as if not dot source)
#RequiresScope Scripts Force - uses a non-global named scope 'scripts' to be the parent one or more script scopes.

The "Scripts" scope would have global as a parent. All scripts added using the "Scripts" directive would be added to this one scope. Basically, it's a special place to dot source scripts other than to global or into another script file's scope. It's sort of like treating one or more non-module scripts as being in a "non-module" module under global.

I don't think there is any value to allowing additional named 'scripts' scopes. "MyScopeForThese5Scripts" and "MyScopeForThose10Scripts"?

@drstonephd Thanks for your submission! Can you clarify how you think the vscode-powershell extesnion would solve this problem? This seems like it's already covered in URL and would need to be implemented in PS and not the extension. Thanks.

@JustinGrote You are correct that this is a PS feature request, not a vscode extension request.

It's not a solution to issue 4568, but a work around. Don't assume modules honor preferences... set them in global. If PS had the directive, then we could use the global scope to set module preferences. At the same time, we could use a special scope for the preferences of other non-module scripts.

There is value in such a directive to make sure scripts are loaded into the correct scope. The author can define the scope in which the script is design to work... if it makes a difference.

Trying to control this in the vscode extension might not be a good idea. Is the choice defined in vscode file by file or for as setting that applies to all files? If I have scripts that load other scripts, it can get pretty tricky if they are not run in the correct order. As it is, I need a special wrapper script to call my scripts if I want the initial script scope in vscode. When using F5, is the choice of global or script enough? I'm confused.

Moved to PS.

Script file directive to select scope during import. #20988

Need straightforward way to honor the caller's preference-variable values / inherited common parameters in functions defined in script modules
This is a longstanding issue that @dlwyatt explained in detail in this 2014 blog post, and he has even published module `PreferenceVariables` with advanced function `Get-CallerPreference` to ease the pain, via a hard-coded list of preference variable names.

In short: A _script_ module's functions do not see the preference-variable values set in the _caller's_ context (except if that context happens to be the _global_ one), which means that **the caller's preferences are not honored**.

_Update: Since implicitly setting preference variables is PowerShell's method for propagating (inheriting) common parameters such as `-WhatIf`, such parameters are ultimately not honored in calls to script-module functions when passed via an advanced function - see #3106, #6556, and #6342. In short: **the common-parameter inheritance mechanism is fundamentally broken for advanced functions across module scopes, which also affects standard modules such as `NetSecurity` and `Microsoft.PowerShell.Archive`**_ .

* From a user's perspective this is (a) surprising and (b), once understood, inconvenient.
Additionally, given that _compiled_ cmdlets do not have the same problem, it is not easy to tell in advance which cmdlets / advanced functions are affected. In a similar vein, compiled cmdlets proxied via implicitly remoting modules also do not honor the caller's preferences.

* From a developer's perspective, it is (a) not easy to keep the problem in mind, and (b) addressing the problem requires a *workaround* that is currently quite cumbersome, exacerbated by currently not having a _programmatic_ way identify _all_ preference variables in order to copy their values to the callee's namespace - see #4394.

A simple demonstration of the problem:

powershell
# Define an in-memory module with a single function Foo() that provokes
# a non-terminating error.
$null = New-Module {
 function Foo {
 [CmdletBinding()] param()
 # Provoke a non-terminating error.
 Get-Item /Nosuch
 }
}

# Set $ErrorActionPreference in the *script* context:
# Request that errors be silenced.
# (Note: Only if you defined this in the *global* context would the module see it.)
$ErrorActionPreference = 'SilentlyContinue'

# Because the module in which Foo() is defined doesn't see this script's
# variables, it cannot honor the $ErrorActionPreference setting, and
# the error message still prints.
Foo

Desired behavior
-----------------

No output.

Current behavior
---------------

none
Get-Item : Cannot find path '/Nosuch' because it does not exist.
...

Environment data
----------------

powershell
PowerShell Core v6.0.0-beta.5 on macOS 10.12.6
PowerShell Core v6.0.0-beta.5 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.0-beta.5 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.483 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)

I found that specifying `$global:` addresses this for progress bar issues.

`$global:ProgressPreference = 'silentlycontinue'` at the top of a script suppresses the performance killing progress indicator when downloading things.

It seems to me that when considering code inside a script module there are two distinct kinds of code to which preference variables (eg. `$ErrorActionPreference`, etc) and common parameters (eg. `-ErrorAction`, etc) might apply:
 - business logic implemented within the module
 * The cause of errors arising from such code are bugs (ie. "boneheaded" errors per Eric Lippert's taxonomy). Accordingly, such code should be run with `$ErrorActionPreference='Stop'`.
 * Deciding the conditions for and quantity of verbose messages output from the business logic requires the good judgment of the module author. This probably involves careful consideration of what should happen when the module is called with the different values of `$VerbosePreference` and `-Verbose` at the call site of module entry points.
 * `$DebugPreference`, `$WarningPreference`, and `$InformationPreference` for such code should probably be the PowerShell defaults regardless of what the caller's values of those variable are.
 - calls made to outside the module
 * Such code is subject to all sorts of untidy unpredictable external realities that cause errors (Eric Lippert calls these "exogenous"). The user of the module should be the party deciding what to do when such an error arises. Accordingly,
 * the value of common parameters and preference variables for such calls should be the same as they were at the call site of the _entry point_ to the module.

The above points aren't hard and fast, but I think they're a reasonable starting point for most modules involving a mix of business logic and calls made to outside the module. PowerShell, of course, does not behave this way by default. To implement a module that is consistent with the above points requires two things to happen as follows:

 1. Capture preference variables and common parameters at the call site of the entry point to the module.
 2. Apply those preference variables and common parameters to the calls made to outside the module.

I suspect that these tasks can be handled reasonably well by a utility module. I wrote an annotated proof-of-concept of such a module. The entry points to a user module that uses the utility module would look, for example, like this:

PowerShell
function Get-MyItem {
 param(
 [Parameter(Position=1)] $Path
 )
 HonorCallerPrefs {
 Get-MyItemImpl $Path
 }
}

function New-MyItem {
 param(
 [Parameter(Position=1)] $Path,
 [switch] $WhatIf,
 [switch] $Confirm
 )
 HonorCallerPrefs {
 New-MyItemImpl $Path
 }
}

The corresponding sites that call out of the user module would look like this:

PowerShell
InvokeWithCallerPrefs {
 Get-Item $path @CallerCommonArgs
}

InvokeWithCallerPrefs {
 New-Item $path @CallerCommonArgs
}

`HonorCallerPrefs{}` and `InvokeWithCallerPrefs{}` are implemented by the utility module and capture and apply the preference variables and common parameters, respectively. The concept should work even if the call stack between `HonorCallerPrefs{}` and `InvokeWithCallerPrefs{}` is deep and complicated, as long as they are in the same module.

The recent #6556 is a more pernicious manifestation of the problem discussed here:

Because CDXML-based cmdlets are seemingly _advanced functions_ rather than binary cmdlets, the functions in the `NetSecurity` module such as `Enable-NetFirewallRule` do not honor the `-WhatIf` switch if invoked via an advanced function that itself supports `-WhatIf`;
ditto for an explicitly set `$WhatIfPreference` value, as discussed.

Revisiting @lzybkr's comment:

From what I gather, PowerShell _implicitly_ translating a common parameter such as `-WhatIf` into the equivalent locally scoped preference variable such as `$WhatIfPreference` is _the_ mechanism for automatically propagating common parameters to calls to other cmdlets inside an advanced function.

@alx9r: As commendable as starting scripts / functions with `$ErrorActionPreference = 'Stop'` is (it is what I usually do in my own code), it actually interferes with that mechanism (I have yet to take a look at your proof of concept).

#6342 is a similar manifestation of the problem, in the context of `Expand-Archive`.

@mklement0

Just to be clear. I did not suggest (or if I did, I did so unintentionally) "starting scripts / functions with `$ErrorActionPreference = 'Stop'`" in the proof-of-concept I proposed. The proof-of-concept is specific to advanced functions in modules. I do suggest that, for advanced functions in modules, the code internal to the module be run with `$ErrorActionPreference = 'Stop'`. But that is quite a different thing from, in general, "starting scripts / functions with `$ErrorActionPreference = 'Stop'`".

That is my understanding too. I think, though, that that mechanism alone produces inadequate results.
 FWIW, the proof-of-concept currently doesn't do any refereeing based on the impact of `-WhatIf`, etc. I see no reason why such a library couldn't be expanded deal correctly with that matter as well.

This issue seems stalled, but it's such an important one, and with the upcoming PowerShell 7.0 milestone it would be really, really great if people put their heads together and come up with a model that makes sense for the caller, has the right default behavior, and that gives the developer the flexibility they need to override the default behavior if necessary.

Agreed. If we can come to a conclusion on this it would be great to get a more consistent model in place.

We could move forward if we created examples of the desired behavior in the form of Perter tests.

The expectation from my POV is that caller preferences that do not affect the script or module execution paths are replicated out to every script or module that gets involved, as a default, without having to opt-in (other than `[CmdletBinding()]` ofc).

This would be things like Verbose, Debug, Information, and Progress, but not something like ErrorActionPreference, PSEmailServer, or ModuleAutoLoadingPreference.

Thinking about the last paragraph in my previous comment a little more, I'm inclined to push for the following to address this (and yes, I'll log this as a separate issue):

Any `ShouldProcess` command that works with PowerShell entities in the current scope (e.g. any of the following commands invoked without `-Scope`: `Clear-Variable`, `New-Variable`, `Set-Variable`, `Remove-Variable`, `Import-Alias`, `New-Alias`, `Set-Alias`, along with any of their corresponding `New-Item`, `Set-Item`, or `Remove-Item` commands) should run without checking `$PSCmdlet.ShouldProcess`. i.e. If `-Scope` is not used, or if `-Scope` is 0, just do it regardless of WhatIf or Confirm preferences. Local scope operations for these commands should be considered safe, because they have no bearing on any parent scopes whatsoever, and are therefore non-destructive. This model should be followed for any command that supports `ShouldProcess` for both actions that may be destructive as well as actions that are non-destructive -- just because `ShouldProcess` is supported in the command, doesn't mean it should be the gatekeeper to all actions taken by that command.

This creates an exception, but one worth having because some commands should only cause WhatIf or Confirm to change how they run some of the time. For example, there are cases where you want to create a set of variables with dynamic names in a loop without ShouldProcess preferences getting in the way of invocation, and while you can do this using APIs, it should be possible to do this using cmdlets since that's what they are for. End users shouldn't have to learn by trial and error which one they should be using -- the cmdlets should just do the right thing.

If that gets accepted, then the last paragraph in my previous post in this discussion becomes a non-issue.

FYI, I opened a set of RFCs to address error handling issues in PowerShell, this one included. If you're keen and you don't want to wait for the RFCs to reach the draft stage, you can find the PR with those RFCs here.

For anyone who has tripped on this issue and is following this discussion, please do share your feedback in URL That PR, the way it is currently written, talks about adopting optional features in PowerShell (described in another RFC: URL

There is some pushback on the optional feature idea because it requires time/resources to properly manage, and it may be too risky to be worth it to the PowerShell Team (see discussion in optional features RFC), in which case you need to ask yourself: is the current problem with how execution preferences do not propagate beyond module or script scope worth fixing even if it may result in breaking changes?

Breaking changes may occur because you would be changing how execution preferences influence existing code without specifically testing that code to make sure that it still works as intended.

From my perspective, I think it is worth it, because the current behavior is the root cause of many issues that show up in different modules. If folks agree, and if the optional feature idea is officially rejected, I can at least set up an experimental feature (these are different from optional features) to allow folks to try it out with their modules and make sure things still work the way they intended with execution preferences properly propagating beyond module or script scope.

I assume this behavior is the root of the issue where ShouldProcess doesn't do verbose output even if VerbosePreference is set? Or should this be a separate issue?

powershell
function Test-Whatif {
 [CmdletBinding(SupportsShouldProcess)]
 param (
 $String = 'Thing to do'
 )
 $target = 'Thing to Target'
 $VerbosePreference ='continue'
 if ($PSCmdlet.ShouldProcess($target,$string)){
 "Did $string to $target"
 }
}

image

Couldn't say off the top of my head, but given that you're setting $VerbosePreference immediately before it, I would be inclined to say that it's likely a separate issue, something to do with how WhatIf only see verbose set by the switch and not an in-session variable.

Sorry if this has already been mentioned, but this thread is quite long so I mostly just skimmed it.

I believe there isn't a single "right answer" here:

For `$ErrorActionPreference`, I personally use

powershell
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

as a header in every module I write, because I want to fail hard when an unhandled error occurs, and my code is written with this in mind. So just blindly copying the variable from caller scope is imo not a good approach, because scripts that do not declare the variable themselves will work differently in different sessions.

For output level preference variables (`$VerbosePreference`, `$InformationPreference`,...), I think the current situation where the output is controlled in each scope separately (so the effective output is the minimum of all set preference variables in all scopes the output passes through) is quite nice and I'd like to keep it both as a module writer and a user.

@MatejKafka: There are two separate aspects, which are _independent_ of one another:

* Designing your module so that it reports the _appropriate_ type of error, based on the official guidelines, summarized here (by me). The same applies to using the other output streams, such as the one for verbose output.

* Respecting the _caller's_ preference variables so as to _modify_ the module's _default_ behavior _on demand_. For that, there's no justification for distinguishing between (a) functions (and scripts) _outside_ a module scope, (b) functions _inside_ a module, and (c) cmdlets.
 * (a) and (c) properly respect the caller's preferences, whereas (b) doesn't. This distinction doesn't make sense, and no user should ever have to think about the _implementation details_ of a given command, i.e. whether they _happen to be_ implemented as (a), (b), or (c).

@mklement0 I agree that the behavior being inconsistent is an issue, but it seems we partially disagree in which direction they should be unified.

Ad 1) - I'm more of a programmer than sysadmin - the concept of a non-terminating error seems like something terrifying to me - an error occurred, meaning that something bad happened and I did not correctly anticipate it and handle it, and the program is in an undefined state. Continuing ahead instead of panicking is imo irresponsible, as I cannot safely reason about the behavior of my own program. Non-terminating error should imo either be a terminating error, or a warning, not a weird mix of both.

I also edited my previous comment, as I found out that my assumption in the last paragraph aren't correct.

It shouldn't do. There's a difference between errors and exceptions. Whether an error is "exceptional" depends on the context. If you've correctly functionally decomposed your code into a series of small pipeline functions each function by itself can't determine if an error is an exception, because it can't own that policy because it doesn't know why it's being called. Errors from that function should bubble through the pipeline to the creator of the pipeline who can, in that context, determine whether the error is exceptional in that context/pipeline.

I would prefer we do not use this Issue to discuss/debate PowerShell's error handling models. There are existing Issues you can pile onto, or start a new one.

Having just fallen foul of this one myself, a *good-enough* syntax (for me), as an occasional AF-author would simply be...

`
Get-Variable -Preference | Set-Variable -Scope Local

`

...where `-Preference` was a new switch added to `Get-Variable` which limited the output of that command to the known preference variables and supplied *the correctly-resolved value for whatever the current scope intended, apropos of any magic that might apply to that preference variable*.

I *think* the intent of such a call would be clear and idiomatic, and—given `-Preference` doesn't exist yet—shouldn't break any backward compatibility, but I've of course only spent a minimal amount of time looking into it, so I am sure there are all manner of cases that I am not considering. I don't *think* it requires alteration to `Set-Variable`, since both `-Name` and `-Value` accept the pipeline input that `Get-Variable` outputs, and `-Scope` does not.

I suppose it might be open to global scope abuse (but, surely so is `$global:*Preference`, so I'm not going to lose sleep over it).

I hit this problem writing my first module. I'm going to revert back to sourcing scripts directly (`. .\foo.ps1`), and not use advanced-function modules going forward.

9+ years for a problem of this impact seems like a long time. Are advanced-function modules considered second-class citizens in PowerShell? Are developers writing binary modules instead? Or is there just very little developer involvement at the module level in general?

@mc-ganduron most likely the issue is complexity of implementation vs. relatively easy workarounds (passing the preference thru to child functions).

I would say abandoning advanced functions for just this is a little dramatic don't you think?

Not at all. First, I have a prior solution available with no workarounds required (sourcing scripts directly). Second, it's reasonable to take first impressions into account. My first experience with advanced-function modules led me to a 9+ year-old bug. I'm not willing to march ahead into other old bugs when I have options available, within PowerShell and without.

@mc-ganduron - All software has bugs. Lots of them are old. This one bothered me as well until the day I was troubleshooting a problem with my module and I only wanted to have verbose output from my module and did not want all of the verbose output noise from all of the other modules and functions my module called. This current way does not seem as convenient or consistent at first, but it does represent an "opt-in" style choice that is more useful than opting out for many troubleshooting scenarios.

Actually I noticed that for errors `$PSCmdlet.ThrowTerminatingError()` works exactly like compiled cmdlet and honor the caller's preference:

powershell
$null = New-Module {
 $ErrorActionPreference = 'Stop'
 function Foo {
 [CmdletBinding()] param()
 trap { $PSCmdlet.ThrowTerminatingError($_) }
 Get-Item /Nosuch
 }
}

$ErrorActionPreference = 'SilentlyContinue'
Foo

I think that it's the most reliable way to handle errors from modules.
I wish the default behavior was like the example above without needing to re-throw the errors. And maybe a way to do the same thing for streams other then errors.

I do wish the syntax for $PSCmdlet.WriteError and ThrowTerminating error was more terse, it looks like black magic when it really should be the way to do it, something like `throwUser` keyword.

I have been scratching my head for months why I didn't get my Debug, Verbose and Information messages in my output when calling Functions in Modules. It's funny when they advise us to move from Write-Host to Write-Information and then make InformationPreference SilentlyContinue the default.

By accident I found this thread and I now prefix DebugPreference, VerbosePreference and InformationPreference with $Global and suddenly I get everything I've been missing, all the feedback I had programmed into my functions but could only see when running from my local system.

So this is absolutely still a thing on PowerShell 7, Mr. Bot.

This is so ugly. I want my debug messages and have no problem getting them. Somehow a module gets the preference. I try as I might to disable the module messages, but to no avail. I don't know if it's the module code trying to get the preference via some tricky means because of this issue or something else. Really, perhaps leave this as version 1 of messaging and create a completely new implementation. And make the new implementation easy to use. A transcript option would be nice if we don't want to liter code with write-debug when we want to see everything. A message level instead many preferences. Multiple targets. Bite the bullet and think of something both easy and useful. Don't make it so we are stuck with backward compatible horrors. I'm sick of this thing.

Please reopen this. Looks like the bot closed it. (Sweeping it under the carpet?)

After that lengthy example, I have to wonder if all I needed to do was like below. In this case Set-StandardDatabaseMail would not have the "hack" code to set the private and global preference values. I don't know if it would handle Debug or Verbose switches as desired. I wish I knew the right way to handle this. If there is no fix, then perhaps a detailed document that explains how we should handle this?

$private:DebugPreference = 'Continue'
$private:VerbosePreference = 'Continue'
$global:DebugPreference = 'SilentlyContinue'
$global:VerbosePreference = 'SilentlyContinue'

Set-StandardDatabaseMail -SqlInstance XXX -WhatIf -InformationAction Continue

If I was using several modules and want to control them individually, this could become very cumbersome. Should preference variables be private by default scoped by fn and module?

Here's a trick to create a new scope if the file was dot sourced. It's not the script scope, but might be okay for a simple call.

& {
$DebugPreference = 'Break'
Test-ScriptScope
}

Host : Visual Studio Code Host - 2023.8.0
Command Origin : Internal (dot sourced?)
Command : C:\Users\rstone\Documents\GitHub\sql-server-maintenance\Test-ScriptScope.ps1
Script Name : Test-ScriptScope.ps1
[Test-ScriptScope.ps1] $global:DebugPreference=SilentlyContinue
[Test-ScriptScope.ps1] $script:DebugPreference=SilentlyContinue
[Test-ScriptScope.ps1] $local:DebugPreference=SilentlyContinue
[Test-ScriptScope.ps1] $DebugPreference=SilentlyContinue
Testing Test-ScriptScop
[Test-ScriptScope] $global:DebugPreference=SilentlyContinue
[Test-ScriptScope] $script:DebugPreference=SilentlyContinue
[Test-ScriptScope] $local:DebugPreference=
[Test-ScriptScope] $DebugPreference=SilentlyContinue
Testing &{} with Test-ScriptScop
[Test-ScriptScope] $global:DebugPreference=SilentlyContinue
[Test-ScriptScope] $script:DebugPreference=SilentlyContinue
[Test-ScriptScope] $local:DebugPreference=
[Test-ScriptScope] $DebugPreference=Break

So many years and no change - we are still struggling with this. mklement0 was pretty spot on from the beginning, and it is hard to grasp the perspectives that has been put onto this, attempting to justify inconsistent behavior with user vs developer perspectives. We're not developing to match everyones expectation, but to produce consistent outcomes and predictable behavior.

Imho - whether you are looking at this from a user perspective, or developer perspective, either one wants consistent behavior, independent of the source of the function thei're invoking. By having a requirement for detailed knowledge of the call stack from start to end, to be able to predict the outcome of preferences, does exactly complicate it for users and developers alike, and especially -WhatIf is a problematic preference variable/common parameter, since it can incur devastating consequences, which ultimately can't be predicted in the current state of affairs, if implemented in an advanced module function.

Keep in mind that in module development, we often call other functions in the module, to deal with specific tasks a greater function needs to accomplish, but at the same time the user/another developer may have the option to call those functions directly.

Users and developers alike would expect e.g. -WhatIf to perform as intended, regardless of how deep the function call is in the call stack. It could be catastrophic if we forgot to import preference variables from the callers scope, and even if we do remember it, the inheritance may have been severed by a module function somewhere else in the call stack that didn't do it - which btw. is completely out of our control, and not fixable by an opt-in change. This leaves the WhatIf parameter risky, and thereby imo useless in a module advanced function, as you cannot guarantee its propagation from parent scopes.

Propagating preference variables to descendent scopes should always have been the way, but the proposed option of adding a CmdletBindingAttribute for opting in to this, is however a truly elegant solution, that would solve part of the problem, and it won't even introduce breaking changes. You may even add more attributes, for more granular control - so one may wonder what is wrong with at least giving us this?

In my modules I have found that you can parse the command that called your module load so you can take action on that....
`[System.Management.Automation.Language.Parser]::ParseInput($MyInvocation.Statement, [ref]$ParsedTokens, [ref]$ParsedErrors)`
This will let you parse the import-module command and the parameters. Since you are using your own invocation statement you do not have to validate the module that is loading is yours.

This is a quick sample of how to do it, incase you are like me and need to see code to understand what these words mean. Drop the following code into a module and when you load it use Verbose switch on the import, it should let you know... you can play with it as you see fit. But I was thinking that it should be able to actually implement this in the import command somehow. I wonder if a proxy command would work... you could do it and throw the parameters that you want into a set order for the 'args' array.... or even modify the bound parameters I guess to do it... thats an idea I haven't thought about... I'll go have some fun with that idea this weekend. Anyways, the code:

`[System.Management.Automation.Language.Token[]]$local:ParsedTokens = @()
[System.Management.Automation.Language.ParseError[]]$local:ParsedErrors = @()
[System.Management.Automation.Language.ScriptBlockAst]$local:LastStatementAst = [System.Management.Automation.Language.Parser]::ParseInput($MyInvocation.Statement, [ref]$ParsedTokens, [ref]$ParsedErrors) # statement should only contain the import-module command
[System.Management.Automation.Language.CommandAst]$local:LastImportCommand = @($local:LastStatementAst.Find({$args[0] -is [System.Management.Automation.Language.CommandAst] -and ([System.Management.Automation.Language.CommandAst]$args[0]).GetCommandName() -eq 'Import-Module'}, $false))[0]
[System.Collections.ObjectModel.ReadOnlyCollection[System.Management.Automation.Language.CommandParameterAst]]$local:LastImportParameters = $local:LastImportCommand.CommandElements | Where-Object {$_ -is [System.Management.Automation.Language.CommandParameterAst]}
[System.Management.Automation.Language.ParameterAst]$local:CalledVerboseAst = @($local:LastImportParameters | Where-Object {$_ -is [System.Management.Automation.Language.ParameterAst] -and $_.ParameterName -eq 'Verbose'})[0]
[bool]$Script:IsVerbose = $false # default state
# update the IsVerbose variable based on the value of the 'Verbose' parameter
if (-not $null -eq $local:CalledVerboseAst.Argument) { # means 'Verbose:[Variable | Value]' was used
 try {
 $script:IsVerbose = $local:CalledVerboseAst.Argument.SafeGetValue($true)
 } catch [System.InvalidOperationException] { # the extent is unsafe
 try { # fallback to extract value from string but compare it to a known valid value to determine the state
 $script:IsVerbose = $local:CalledVerboseAst.Argument.Extent.Text.Replace('$','').ToUpper() -eq 'TRUE'
 } catch { # ya, that extent is really unsafe
 $script:IsVerbose = $false # no hope so we just say false
 }
 }
} else { # else only the switch is present, which means true for the value
 $script:IsVerbose = $true
}

Write-Host "Verbose was $(($Script:IsVerbose ? "used with a resolved value of $IsVerbose" : "not used"))"
`
I just wish I could make it cleaner and more compact that it would be not so distracting at the top of a module.

This was closed as 'completed' in Nov 2023, but seems to still be an issue. It's frustrating having to work around this issue with `-Verbose:($PSBoundParameters['Verbose'] -eq $true)` everywhere.

@SteveL-MSFT this is a bot-closed issue that is still active and should be reopened.

Maybe this is helpful. It would be nice to have something baked in but this `Sync-ModulePreferences`. It solves the original issue and is pretty flexible. No way that I know of to automatically grab the full list of preference variables but hard coded works. You could even pass `Sync-ModulePreferences *` if you wanted to cover all loaded modules but like others, I'm a bit skittish going that far.

powershell
function Sync-ModulePreferences {
 [CmdletBinding(DefaultParameterSetName='Names')]
 param(
 [Parameter(Mandatory,ValueFromPipeline,ParameterSetName='Names')]
 [ValidateNotNullOrEmpty()]
 [string[]] $ModuleName,

 [Parameter(Mandatory,ValueFromPipeline,ParameterSetName='Objects')]
 [System.Management.Automation.PSModuleInfo[]] $ModuleObject,

 [Parameter(HelpMessage='Subset of preferences to sync')]
 [string[]] $Include,

 [Parameter(HelpMessage='Subset of preferences to exclude from sync')]
 [string[]] $Exclude,

 [ValidateNotNull()]
 [System.Management.Automation.SessionState] $SessionState = $ExecutionContext.SessionState
 )

 $Preferences = @(
 'ConfirmPreference', 'DebugPreference', 'ErrorActionPreference'
 'ErrorView', 'FormatEnumerationLimit', 'InformationPreference'
 'Log*Event', 'MaximumHistoryCount', 'OFS'
 'OutputEncoding', 'ProgressPreference', 'PSDefaultParameterValues'
 'PSEmailServer', 'PSModuleAutoloadingPreference', 'PSNativeCommandArgumentPassing'
 'PSSessionApplicationName', 'PSSessionConfigurationName', 'PSSessionOption'
 'PSStyle', 'Transcript', 'VerbosePreference'
 'WarningPreference', 'WhatIfPreference', 'PSNativeCommandUseErrorActionPreference'
 ) |
 Where-Object {
 $IsIncluded = if ($Include) { $_ -in $Include } else { $True }
 $IsExcluded = if ($Exclude) { $_ -in $Exclude } else { $False }
 $IsIncluded -and -not $IsExcluded
 }

 $Preferences

 $Modules = if ($PSCmdlet.ParameterSetName -eq 'Names') { Get-Module $ModuleName } else { $ModuleObject }

 foreach($Module in $Modules) {
 Write-Verbose "Updating Module '$Module'"
 foreach ($Preference in $Preferences) {
 $CallerValue = $SessionState.PSVariable.GetValue($Preference)
 $ModuleValue = $Module.SessionState.PSVariable.GetValue($Preference)

 if ($CallerValue -is [Hashtable]) {
 foreach ($CallPair in $CallerValue.GetEnumerator()) {
 $ModPairValue = if ($ModuleValue.($CallPair.Name)) { $ModuleValue.($CallPair.Name) }

 if ($CallPair.Value -ne $ModPairValue) {
 Write-Verbose "Updating Preference '$Preference.$($CallPair.Name)' from '$ModPairValue' to '$($CallPair.Value)'"
 $ModuleValue[$CallPair.Name] = $CallPair.Value
 }
 }
 } elseif ($CallerValue -ne $ModuleValue) {
 Write-Verbose "Updating Preference '$Preference' from '$ModuleValue' to '$CallerValue'"
 $Module.SessionState.PSVariable.Set($Preference, $CallerValue)
 }
 }
 }
}

# Define an in-memory module with a single function Foo() that provokes
# a non-terminating error.
$Mod = New-Module {
 function Foo {
 [CmdletBinding()] param()
 Write-Host "NoNewLine"

 # Provoke a non-terminating error.
 Get-Item /Nosuch

 Write-Verbose "Foo"
 }
}

$ErrorActionPreference = 'SilentlyContinue'
$VerbosePreference = 'Continue'
$PSDefaultParameterValues.Add('Write-Host:NoNewLine', $True)

Sync-ModulePreferences `
 -Verbose `
 -ModuleObject $Mod `
 -Include @('ErrorActionPreference', 'VerbosePreference', 'PSDefaultParameterValues', 'ConfirmPreference') `
 -Exclude ('ConfirmPreference')

Foo

## Update modules on import
# Import-Module Pester -PassThru | Sync-ModulePreferences

## Example Output
#VERBOSE: Updating Module 'Pester'
#VERBOSE: Updating Preference 'ErrorActionPreference' from 'Continue' to 'SilentlyContinue'
#VERBOSE: Updating Preference 'PSDefaultParameterValues.Write-Host:NoNewLine' from '' to 'True'
#VERBOSE: Updating Preference 'VerbosePreference' from 'SilentlyContinue' to 'Continue'

@RiverHeart You could remove any variable ending with "preference" from being hardcoded by changing your variable definition of Preferences to:

`powershell
$Preferences = @(
 'ErrorView', 'FormatEnumerationLimit', 'Log*Event'
 'MaximumHistoryCount', 'OFS', 'OutputEncoding',
 'PSDefaultParameterValues', 'PSEmailServer', 'PSNativeCommandArgumentPassing'
 'PSSessionApplicationName', 'PSSessionConfigurationName', 'PSSessionOption'
 'PSStyle', 'Transcript'
 ) + @(
 Get-ChildItem -Path "Variable:*preference" | Select-Object -ExpandProperty 'Name'
 ) |
 Where-Object {
 $IsIncluded = if ($Include) { $_ -in $Include } else { $True }
 $IsExcluded = if ($Exclude) { $_ -in $Exclude } else { $False }
 $IsIncluded -and -not $IsExcluded
 }

`
If you would rather, you could also use
` Get-Variable -Scope 'Global' | Where-Object { $_.Name -ilike '*preference' } | Select-Object -ExpandProperty 'Name'
` to do the same thing instead of the
` Get-ChildItem -Path "Variable:*preference" | Select-Object -ExpandProperty 'Name'
` This of course does have the side effect of picking up any variable ending in the word "Preference" which I see why one wouldn't want to and why you would want to.

Thank you though @RiverHeart for sharing as that has proven to be far better than what I have been doing!

I tested the demonstration block from the first post and it seems to work as intended, i.e. no output is produced (as opposed to when I define `$ErrorActionPreference = 'Stop'`.

Has this been fixed already?

Name Value
---- -----
PSVersion 7.5.2
PSEdition Core
GitCommitId 7.5.2
OS Microsoft Windows 10.0.22621
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0

I don't think so. If you run the example from the terminal it works since `$ErrorActionPreference = 'Stop` also sets `$Global:ErrorActionPreference` which the module can see but if you put that code in a script and call it (eg `./CallPrefTest.ps1`) instead of using ISE or VSCode it behaves as described since only script scope is changed.

Even worse with `-WhatIf`:

powershell
$null = New-Module {
 function main {
 [CmdletBinding(SupportsShouldProcess)]
 param ()
 destructive
 }
}

$null = New-Module {
 function destructive {
 [CmdletBinding(SupportsShouldProcess)]
 param ()

 if ($PSCmdlet.ShouldProcess("sub", "destructive process")) {
 Write-Host "applying destructive process"
 }
 }
}

main -WhatIf

Expected output: `What if: Performing the operation "destructive process" on target "sub".`
Actual output: `applying destructive process`


Question: Tutorial around building a wireless hotspot to bypass captive portals?

**Note:** Documentation should be updated to reflect the *latest* version of the OS. So we're going to go through and make sure it all works with Bookworm. We may need some NOTE blocks that mention "for previous versions of Raspberry Pi OS" from time to time, but these need to be kept short (a couple of medium-length paragraphs at most). We do not have the availability to support multiple versions of the OS in the documentation going forward with breaking changes like Wayland and Network Manager happening.

Tutorial around building a wireless hotspot to bypass captive portals
i have the actual Raspi OS `2022-09-22-raspios-bullseye-armhf.img` version installed to my RPi Zero W and tried to set it up as an AP+STA.
for the AP part i watched the guide for Setting up a Routed Wireless Access Point.
but it looks this guide is outdated.

there it is written `Buster` is the newest version instead of `Bullseye`.

and they use `iptables` but in the current Raspi OS `iptables` is not installed anymore.
`sudo: iptables: command not found`
and its transformation from `iptables` to `nftables` from the earlier version of RaspiOS Bullseye seems to be gone as well.

Honestly somewhat tempted to remove this section, and the following section as well. Feels like something that can be better deal with with the new tutorials section of the site.

<img width="1505" alt="Screenshot 2022-11-05 at 13 28 46" src=" URL

See also #2314.

Right. I think we should yank this, and the bridge mode section, and rewrite as a tutorial for the main site. Assigning it to @tobybroberts.

Primarily using `NetworkManager` 'cause it's the new hotness and that's what people will have (ping @tobybroberts), but potentially both I guess depending on how much overhead of extra effort (and awkwardness) it adds to the tutorials.

@tobybroberts wrt our conversation earlier today, we should merge the routed and bridged tutorials together into one "setting up a wireless access point".

`NetworkManager` is the new standard then i am fine when there is only a tutorial for that available. thank you in advanced,

when i can add some wishes, please also try to make a tutorial for AP + STA mode.
e.g. for the RPi Zero W it would be nice to have STA and AP simultanuosly on its wlan.
there are some old uncomplete guides out there, but none is using `NetworkManager` to do that yet.

but the tutorial section hasn't changed and is still outdated

It's actually more or less at the top of the to do list, someone should be looking at it next week.

@lurch Talking to @jehlers42 right now and this part of the docs (highlighted in red) still seem to be present on the `bookworm` branch. Shouldn't all this stuff be deleted from the branch at this point. The tutorials still need to be written but I thought you'd told me you'd deleted the text from the branch at this point? If not everything in the red box needs to go.

@jehlers42 can you figure out what text needs to go, and get rid of it from the `bookworm` branch. Post the commit back to this thread, and leave the issue open, 'cause we still need to write the updated tutorial(s) which will end up in Wordpress.

...and they are no longer in the branch. Leaving this issue open because someone (me, @tobybroberts, Nate perhaps when he joins) needs to write replacement tutorials (in Wordpress).

Nope, I don't ever remember claiming that. I was leaving the text in-situ in case it'd be a useful reference for whoever ends up writing the replacement tutorials? But you're right, they should definitely be removed from the `bookworm` branch before it gets merged :+1:

On a vaguely-related note, I wonder if it'd be useful to have a "link-to-tutorial boxout" (like @nelliemckesson has done for PIP and the RPi Press books) that we could use to link from the documentation to the tutorials? :thinking:

@nathan-contino So this is us yanking tutorial content that shouldn't live here and writing a new one in Wordpress (and then we can use that tutorial macro stuff, see #3082 to link back to it the documentation in the right place)

@nathan-contino Going to reopen this issue as there is still a Wordpress tutorial associated with it to write!

Live at URL

There will also be a tutorial going into URL at some point soon.

is the RPi onboard WiFi able to do AP + STA at the same time? and if so, how to do this to get AP + STA running?

Update documentation for ahead of Bookworm
~We now offer both Bullseye and Buster (Legacy) releases of Raspberry Pi OS. However some features work in one but not the other, and vice-versa.~

~@JamesH65 has an internal document which is probably a useful starting point for this.~

(edit by @aallan) We need to update the documentation for Bookworm. Online documentation will focus on supporting Bookworm only. There will be NOTE blocks referencing that "things worked differently" in the previous (legacy) version if that's appropriate/needed. We'll try and keep those blocks short.

And perhaps URL and/or URL ought to mention the different versions too?

This is already underway internally, but it's a private repo.

Should stay open. Still some updating needed. See also #2398.

@aallan
Are you simply updating the vlc and omx examples according to the version?

OMX Player no longer works under Bullseye. All the examples using it in the documentation need to be replaced with an equivalent invocation for VLC (or other relevant software), see #2398 which is the linked issue.

However this issue is the more general "other things that Bullseye broke" issue. There are some other things beyond the OMX Player issue that haven't yet been fixed.

If there is something to be done externally, I would be happy to contribute.

Headline things:

* X goes away and is replaced by Wayland
 - nominally a big thing, but there has been a lot of work to keep the user experience the same
 - but some change is inevitable
* dhcpcd goes away and is replaced by Network Manager
* random bookworm stuff

Current tasks associated with this issue:

[tasklist]
### Bookworm Issues
- [ ] URL
- [ ] URL
- [ ] URL

this task list will expand rapidly when @lurch does the documentation audio.

Child-issues:
* #2999
* #2947
* #2948
* #2949
* #2950
* #2951
* #2952
* #2953


Question: make_fx fails under TorchRefsMode context?

Looks like there's some example of how `var.X` overloads are handled in refs. I'll follow that pattern and get overloads of Tensor.to plumbed through.

make_fx fails under TorchRefsMode context
### 🐛 Describe the bug

Run into this issue with torchdynamo/benchmarks/huggingface.py with a custom stack (nvprim).

Tried to get a small repro but failed. However, I did manage to get a different failure in this small example vvv:

import torch

x = torch.empty(1024, 1, device="cuda")
target = torch.empty(1024, device="cuda").long()

def func(x, target, index):
 nll_loss_forward = torch.ops.aten.nll_loss_forward.default(x, target, None, 1, index)

from torch.fx.experimental.proxy_tensor import make_fx

from torch._decomp import get_decompositions
decomp_table = get_decompositions({torch.ops.aten.nll_loss_forward})
gm = make_fx(func, decomposition_table=decomp_table)(x, target, 512) # tracing with decomposition works
print(gm.graph)

from torch._prims.context import TorchRefsMode
with TorchRefsMode():
 gm = make_fx(func)(x, target, 512) # somehow tracing here with decomposition breaks.
 print(gm.graph)

Output

graph():
 %x_1 : [#users=1] = placeholder[target=x_1]
 %target_1 : [#users=3] = placeholder[target=target_1]
 %index_1 : [#users=0] = placeholder[target=index_1]
 %unsqueeze : [#users=1] = call_functiontarget=torch.ops.aten.unsqueeze.default, kwargs = {})
 %gather : [#users=1] = call_functiontarget=torch.ops.aten.gather.default, kwargs = {})
 %squeeze : [#users=1] = call_functiontarget=torch.ops.aten.squeeze.dim, kwargs = {})
 %neg : [#users=1] = call_functiontarget=torch.ops.aten.neg.default, kwargs = {})
 %ne : [#users=1] = call_functiontarget=torch.ops.aten.ne.Scalar, kwargs = {})
 %scalar_tensor : [#users=1] = call_functiontarget=torch.ops.aten.scalar_tensor.default, kwargs = {dtype: torch.float32, layout: torch.strided, device: cuda:0})
 %where : [#users=1] = call_functiontarget=torch.ops.aten.where.self, kwargs = {})
 %ne_1 : [#users=1] = call_functiontarget=torch.ops.aten.ne.Scalar, kwargs = {})
 %sum_1 : [#users=1] = call_functiontarget=torch.ops.aten.sum.default, kwargs = {})
 %_to_copy : [#users=1] = call_functiontarget=torch.ops.aten._to_copy.default, kwargs = {dtype: torch.float32, device: cuda:0})
 %sum_2 : [#users=1] = call_functiontarget=torch.ops.aten.sum.default, kwargs = {})
 %div : [#users=0] = call_functiontarget=torch.ops.aten.div.Tensor, kwargs = {})
 return None
Traceback (most recent call last):
 File "/jiej/playground/repro_control_flow.py", line 19, in
 gm = make_fx(func)(x, target, 512)
 File "/opt/pytorch/pytorch/torch/fx/experimental/proxy_tensor.py", line 622, in wrapped
 t = dispatch_trace(wrap_key(func, args, fx_tracer), tracer=fx_tracer, concrete_args=tuple(phs))
 File "/opt/pytorch/pytorch/torch/fx/experimental/proxy_tensor.py", line 392, in dispatch_trace
 graph = tracer.trace(root, concrete_args)
 File "/opt/pytorch/pytorch/torch/fx/_symbolic_trace.py", line 739, in trace
 (self.create_arg(fn(*args)),),
 File "/opt/pytorch/pytorch/torch/fx/experimental/proxy_tensor.py", line 406, in wrapped
 out = f(*tensors)
 File "/jiej/playground/repro_control_flow.py", line 7, in func
 nll_loss_forward = torch.ops.aten.nll_loss_forward.default(x, target, None, 1, index)
 File "/opt/pytorch/pytorch/torch/_ops.py", line 60, in __call__
 return self._op(*args, **kwargs or {})
 File "/opt/pytorch/pytorch/torch/overrides.py", line 1778, in wrapped
 return f(self, *args, **kwargs)
 File "/opt/pytorch/pytorch/torch/_prims/context.py", line 187, in __torch_function__
 return func(*args, **kwargs)
 File "/opt/pytorch/pytorch/torch/_decomp/decompositions.py", line 1740, in nll_loss_forward
 total_weight = (target != ignore_index).sum().to(self)
 File "/opt/pytorch/pytorch/torch/overrides.py", line 1778, in wrapped
 return f(self, *args, **kwargs)
 File "/opt/pytorch/pytorch/torch/_prims/context.py", line 187, in __torch_function__
 return func(*args, **kwargs)
 File "/opt/pytorch/pytorch/torch/_refs/__init__.py", line 1697, in to
 return prims.convert_element_type(a, dtype)
 File "/opt/pytorch/pytorch/torch/_ops.py", line 60, in __call__
 return self._op(*args, **kwargs or {})
 File "/opt/pytorch/pytorch/torch/overrides.py", line 1778, in wrapped
 return f(self, *args, **kwargs)
 File "/opt/pytorch/pytorch/torch/_prims/context.py", line 168, in __torch_function__
 return orig_func(*args, **kwargs)
 File "/opt/pytorch/pytorch/torch/_ops.py", line 60, in __call__
 return self._op(*args, **kwargs or {})
RuntimeError: prims::convert_element_type() Expected a value of type 'int' for argument 'dtype' but instead found type 'Tensor'.
Position: 1
Value: tensor([[0.],
 [0.],
 [0.],
 ...,
 [0.],
 [0.],
 [0.]], device='cuda:0')
Declaration: prims::convert_element_type(Tensor a, int dtype) -> Tensor
Cast error details: Unable to cast Python instance to C++ type (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)

The original error I'm getting is `It appears that you're trying to get value out of a tracing tensor - erroring out! It's likely that this is caused by data-dependent control flow or similar.`
which seems to be originated from tracing with decomposition inside `TorchRefsNvfuserCapabilityMode`

To repro the original issue: running with torchdynamo code from here: URL
run it with `python benchmarks/huggingface.py --training -d cuda --fast --nvprims-nvfuser --skip-accuracy-check --generate-aot-autograd-stats --dump-raw-metrics --float32 -k AlbertForQuestionAnswering`

### Versions

Running with pytorch

commit 9addeccb6b1ec9fed0246ba18fdb70550c813a90 (HEAD, origin/master, origin/HEAD, master)
Author: kshitij12345
Date: Thu Sep 8 06:23:12 2022 +0000

 [functorch] vmapvjpvjp (re-enable test with skips and xfails) (#83999)

 Enable `vmapvjpvjp` test and add relevant skips and xfails.
 Pull Request resolved: URL
 Approved by: URL

torchdynamo commit

commit cad8185c937f2396ba1c683b86844c0248f2f538 (ivan/nvprims-backend)
Merge: dcd88d1 11873be
Author: Ivan Yashchuk
Date: Thu Sep 1 10:13:19 2022 +0300

 Merge remote-tracking branch 'upstream/main' into nvprims-backend

cc @ezyang @mruberry @ngimel @SherlockNoMad @soumith

To clarify, #84735 is NOT a proper solution. I started that PR so we can at least avoid similar failures in torchbench. But there's probably some sharp corner in our tracing that we should get it properly fixed.

I still think y'all should be using TorchRefsMode to do decompositions...

hahaha, you are probably right from the beginning. But I don't know enough to comment on this, I'll let @IvanYashchuk make the right call~~

Here's what really happens:

py
import torch
from torch._prims.context import TorchRefsMode
a = torch.randn(3, 3, device='cuda')
b = torch.randn(3, 3, device='cuda')

def func(a, b):
 return a.to(b)
with TorchRefsMode():
 func(a, b)

py
RuntimeError: prims::convert_element_type() Expected a value of type 'int' for argument 'dtype' but instead found type 'Tensor'.
Position: 1
Value: tensor([[-0.0440, -0.6463, -1.2029],
 [ 0.8581, -0.1144, -0.2697],
 [ 0.3353, 0.1361, -1.8018]], device='cuda:0')
Declaration: prims::convert_element_type(Tensor a, int dtype) -> Tensor
Cast error details: Unable to cast Python instance to C++ type (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)

It's not a problem with `TorchRefsMode()` it's a problem with `torch._refs.to`. There are tests that are supposed to verify calling `tensor.to(tensor)`:
 URL
And there's an issue for implementing this: URL

Closing as duplicate.

@kevinstephano The majority of decomps could be applied via the decompositions table that proxy tensor tracing respects (or you can apply yourself in a TorchDispatchMode). The key is that the decomposition happens later; instead of forcing yourself to accurately handle all Python frontend quirks, you can decompose after it's gotten through the Python arg parser and gotten normalized.

PrimTorch targets implementing references for all Python frontend quirks. And we are working towards supporting PrimTorch.

There's a nice feature that for operations that overlap in ATen and Python's PyTorch it's possible to register the reference implementations to the decomposition table of `torch._decomp`. So that TorchDispatchMode users can benefit from increased PrimTorch coverage of references.
 URL

The requirement to support aten->refs mapping is a temporary workaround because backward rules are not yet implemented for prims and AOT Autograd produces a graph with `torch.ops.aten` calls by default. Soon when prims gain backward support we won't need aten->refs mapping.

Thank you, I've heard multiple times how targeting internal ATen CompositeExplicitAutograd functions is great. I will stick with PrimTorch though, supporting Python's user-facing interface, and I will not pivot towards making "ATen CompositeExplicitAutograd" (`torch._decomp.decomposition_table`) the primary target for nvFuser execution.

Support more overloads of Tensor.to in torch._refs.to
### 🚀 The feature, motivation and pitch

There are multiple overloads of `to`, but currently only one overload is supported in `torch._refs.to`
aten/src/ATen/native/native_functions.yaml lists all overloads:
 URL
Missing overloads:

- [ ] to.dtype_layout
- [ ] to.device
- [ ] to.other

### Alternatives

_No response_

### Additional context

_No response_

cc @ezyang @mruberry @ngimel @jjsjann123


Question: Error: detected space-or-tab-containing sequence?

Hi Dong-Ha,

I am sorry for that, just fixed the issue (I assigned updated chrome names to the wrong fields...) URL

Now they are correct.

- Bogdan

Error: detected space-or-tab-containing sequence
Hi, I am trying to run this pipeline through Anaconda and I am getting the following error:

_Error! File: data/Nitens-and-Greg/GCF_021461395.2_iqSchAmer2.1_genomic.fna - detected space-or-tab-containing sequence:
NC_060119.1 Schistocerca americana isolate TAMUIC-IGC-003095 chromosome 1, iqSchAmer2.1, whole genome shotgun sequence
Please exclude or fix sequences with spaces and tabs._

From what I can tell, it is a problem with the formatting of the header in the fasta file as suggested in the GitHub. I have seen the script to rename after running but there is no script to rename before. do you have a script I can use or a suggestion on how to fix this error? I have included a screenshot of the full run below.

I am trying to run this on very large RefSeq genomes (~8Gb) and I would appreciate any help you can offer!

Screenshot 2024-06-18 163252

Hi, @MichaelHiller and @kirilenkobm. I just wanted to add details to this request. We understand this is probably an issue because we use the chromosome with "NCXXX.Y," specified in issue #8 #3 and added in the README. Still, we would appreciate knowing what is the best method to rename here and being able to use your custom scripts to rename afterward `standalone_scripts/rename_chromosomes_back.py.`

We want to use `make_lastz_chain` and `TOGA` to check whether the ortholog detection using RefSeq on some of our genomes could be improved compared to OrthoFinder, so we want to keep the GCF type. I am sure the solution is very straightforward, and I am sorry for the silly question. Bioinformatics is hard, even after many years!! o(>.<)o

Thanks for your time!

I believe I've corrected it myself, the code I used is below. and was saved into a .sh file

#!/bin/bash

# Define the input and output files
input_file="input-name.fna"
output_file="input-name_only_contig_name.fna"

# Use sed to process both headers and sequences in one pass
sed -e 's/^\(>\S*\).*/\1/' "$input_file" > "$output_file"

echo "Processing complete. Output written to $output_file."

Renaming sequence in the chain has an issue.
Hi again,
I saw the update to deal with the sequence IDs with "." (per issue #3):

Since it appears that you implemented a mechanism to deal with the ".*" in sequence IDs, I downloaded the new version of the pipeline and ran it with the input genomes without modifying sequence IDs.

The pipeline started with creating a renamed `.fasta` file and a `.tsv` that contains the sequence ID conversion table. And at the end, the log says the pipeline is renaming chromosome names in the chain file.

However, the resulting chain file does not look right. Most of all, the chain score field is gone, making it impossible to salvage the results:

$ zgrep "chain" h38w5.m39w5.allfilled.chain.gz | head -n5 | column -t
chain NC_000014.9 NC_000014 107043718 + 24687985 NC_000078.7 NC_000078 120092757 + 44683557 114519917 1
chain NC_000004.12 NC_000004 190214555 + 1103677 NC_000071.7 NC_000071 151758149 + 33338229 105126044 2
chain NC_000002.12 NC_000002 242193529 + 96496148 NC_000067.7 NC_000067 195154279 + 36305135 93990572 3
chain NC_000001.11 NC_000001 248956422 + 930892 NC_000070.7 NC_000070 156860686 - 516431 53690008 4
chain NC_000001.11 NC_000001 248956422 + 68121445 NC_000069.7 NC_000069 159745316 - 100601 72842298 5

For comparison, below is the chain file using a previous version of `make_lastz_chains`. Here, I supplied the input genomes with sequence IDs pre-modified:

$ zgrep "chain" h38w4.m39w4.all.chain.gz | head -n5 | column -t
chain 720570302 NC_000014__9 107043718 + 24687985 106824309 NC_000078__7 120092757 + 44683557 114419863 1
chain 598452391 NC_000004__12 190214555 + 1104636 88140396 NC_000071__7 151758149 + 33339160 105126044 2
chain 584782083 NC_000001__11 248956422 + 930892 58547094 NC_000070__7 156860686 - 516431 53690008 3
chain 578674369 NC_000002__12 242193529 + 96496148 241869966 NC_000067__7 195154279 + 36305135 93989195 4
chain 564776354 NC_000001__11 248956422 + 68121445 158184951 NC_000069__7 159745316 - 100601 72842298 5

Is there any other part of the pipeline updated since July 6th, 2022? If not, we will revert back to the older version (make_lastz_chains) and use genome files with the modified sequence IDs. The current version has an issue.

Thanks,
Dong-Ha

Thanks, Bogdan, for the quick response.

Is there anything else updated since July 6th, 2022, other than the renaming of sequence IDs?

 Dong-Ha

Thanks, Bogdan, for responding quickly. I have already submitted a round of runs using genomes renamed ("." -> "__") manually. I will test this fix in the next round and close the ticket when it goes through.

Dong-Ha

I tested the script downloaded on Oct. 10th (before the fix for #10 but after URL and it worked well with sequence IDs that contain "." and generated the correct `chain.gz` file.

Thanks!
Dong-Ha


Question: What is the nullness signature of a multiply-inherited abstract method?

**Revised Proposal**: As described in JSpecify Conformance: Questions and Answers, conformance tests will check that tools can recognize when a method's static return type is not a nullness subtype of that of the directly overridden method, or a parameter type is not a nullness supertype of that of its direct superparameter. JSpecify will impose no requirement on tools to report anything in particular to users in these cases.

Is this enough to change your thumb's direction, @kevinb9n?

What is the nullness signature of a multiply-inherited abstract method?
[EDIT: this whole comment is about case 1, where the method is abstract because all inherited methods are abstract.]

First consider a discrepancy in return types:

// in null-marked context

interface Foo { @Nullable String get(); }
interface Bar { /*non-nullable*/ String get(); }
interface Qux extends Foo, Bar {}

In this case, we can probably just follow Java's lead. With a quick experiment it seems that it won't just happily gin up an arbitrary intersection type, but if one of the types is more specific than the other (as should always be the case for us), it seems to go with that. (Or maybe I've gotten it wrong, but whatever it does, we can probably(?) stay consistent with.)

// in null-marked context

interface Foo { void accept(@Nullable String x); }
interface Bar { void accept(/*non-nullable*/ String x); }
interface Qux extends Foo, Bar {}

Here, Java is no guide, because any discrepancy in the types results in both overloads existing separately in `Qux` which we obviously can't mirror. (Or if they have the same erasure it just complains.)

It seems reasonable to go with the broader type; implementing `Foo` requires it to accept null, whereas `Bar` doesn't care whether it does or not. But is this tantamount to supporting contravariant nullness in parameter overrides, which we've said in #49 we don't intend to do?

I do think this case is exactly #111, in different clothing.

I think I agree? So to restate, then:

To find the signature of an abstract method inherited from multiple supertypes, use the intersection the supermethod return types, and the union of each set of corresponding parameter types.

I think we can resolve this.

Of course, we can't express union or intersection types. Where we said "use the intersection of the supermethods' return types", I think we meant the glb; likewise lub for parameter types, with both being restricted to what we can express.

But we're also limited by what javac will allow: we can't change the base type at all.

I'm not sure we considered a case like this, where the nullness varies for a non-root type. What is the parameter type of `AB.foo`?

java
// null-marked code
interface SuperA { void foo(List bar); }
interface SuperB { void foo(List bar); }
interface AB implements SuperA, SuperB {}

The lub of these two types would be `List `, but we can't do that.

If we are analyzing AB itself, we can say: "please override this method and choose which of the two signatures you want". (Of course, whichever way they choose they'd still get a warning about the other one.)

But what about when AB is a dependency?

One option is: the answer is `List `, with the reasoning that type parameters are *more* likely covariant than contravariant, so we might as well behave as though `? extends` *were* there.

So, throughout all components of parameter types, *except* those that actually use `? super` (which we can handle normally), we would use the "most nullable" of the types. For return types, the least nullable.

Just to state that more directly: for this purpose only, treat wildcardless type arguments as if `? extends` is there. Would that resolve every case?

@cpovirk floated an intriguing alternative: the inherited method gets the parameter type `List `. This seems to make a lot of sense to me: in order to specify it, we needed them to provide an explicit override, and they didn't, so it's unspecified.

TODO: check into what javac does with base types; write test-case-like code

I'm not sure what I meant to learn from javac. If there's any variation in parameter types at all, it just gives an error -- we knew that! I guess what it does with return types is a bit illustrative:

java
import java.util.*;

class Issue110 {
 interface A { List foo(); }
 interface B { List foo(); }
 interface C extends A, B {}

 static {
 C c = null;
 List list = c.foo();
 }
}

This does compile. In other words, it's happy to go ahead and pick the more specific type. But this is just further argument justifying the *original* decision here from way back when. If I take out all the `? extends` it refuses to compile `C` at all. Again though, we knew this.

As mentioned I will write out test cases, but they'll be... long. We'd normally not wait to mark this issue resolved until we do that, unless anyone feels that we don't even understand what we're deciding yet without writing all that out.

I had forgotten about this one! :)

It is a _little_ weird that someone might write...

java
interface Foo { @Nullable String passThrough(@Nullable String s); }
interface Bar { String passThrough(String s); }
interface Qux extends Foo, Bar {}

...and end up as if `Qux` had a signature like `String passThrough(@Nullable String s)`, which is presumably unsound.

In #67, I'd cited URL which appears to match kevinb9n's results. It's similar to our rule in that it picks the most specific return type.

But we go further by trying to perform a full on glb/lub of multiple types. For example, the JLS wouldn't "merge" `Iterable ` and `List ` into `List `, but we're effectively trying to do that. But we can make that happen because we know that the base types match—well, _mostly_.

Arguably a more JLS-like approach would be pick one of the _n_ signatures. Maybe it would make sense to pick the one with the more specific return type (since that's the part that the JLS allows to vary). Granted, even "more specific return type" isn't a well-defined concept: If we inherit both `@Nullable List ` and `List `, then neither is strictly more specific than the other. So we're back to glb/lub and possibly even unspecified nullness.

(Maybe ideally a checker that analyzes _that class_ would produce an error to get the programmer to resolve the conflict. But programmers can avoid any such error by suppressing or at least by not running a checker in the first place. So there's no getting around defining behavior for a checker that analyzes _usages_ of such a method.)

(I'm here because @kevinb9n just pointed out to me in chat that there's a related but separable issue: If `Qux` _declares_ some `passThrough(String)` method, then checkers should probably check it against _both_ of the supertypes' methods _separately_. The question of _this_ issue is what happens when there is no such declaration in `Qux`.)

Hmm, URL has me thinking more about unspecified nullness.

I've read the description there, and I'm not sure if it adds behavior beyond what glb/lub already does. I may be misunderstanding, though.

One possible goal could be to prefer to _ignore_ unspecified when we have "better" information:

java
@NullMarked
interface Foo {
 void use(String s);
}

@NullUnmarked
interface Bar {
 void use(String s);
}

interface Qux extends Foo, Bar {}

There, the unspec rule from above and the glb/lub rule give us `void use(String*)`, I think? But we could instead say that the type is `void use(String!)`, since we have an affirmatively non-nullable type from `Foo`. Of course, someone could in the future annotate `Bar` with `@Nullable String`, in which case the type would become `String*` again because of the conflict. But maybe that's overall a better user experience, since the type probably is meant to be `String!`.

This spec-unspec mix may well be the most common kind of "conflict" that we'd see in practice, so we might want to err on the side of doing the "right" thing for it.

What to do when overriding method's annotations indicate weaker contract than overridden method [working decision: finding of distinct category]
We seem to lean toward allowing covariant return types and contravariant parameter types (in the nullness dimension). These are ordinary contractual refinements [EDIT: strengthenings]

I want to discuss *backward* refinements [EDIT: contractual weakenings]: covariant parameters and contravariant returns. Surprisingly, I'm going to claim these are also valid.

Scenario A: `Foo.bar()` has a non-nullable return type. `SubFoo.bar()` _should_ not return null in any case, but for whatever reason, its author has decided to do so and no one will change their mind. (This situation could also arise from `Foo` changing after the fact.)

From jspecify's point of view, I think that `@Nullable` is the only correct way to annotate the return type of `SubFoo.bar()`, and the user should absolutely do so. That way, at least consumers who _happen_ to have the static type `SubFoo` will behave correctly, and that is better than nothing.

From the "what our annotations mean as specification" perspective, there is nothing wrong here. It's just that from the "preventing bugs" perspective, any reasonable checker is going to want to issue a warning on `SubFoo.bar()`, explaining that it risks causing an NPE for anyone using `SubFoo` _via_ its `Foo` supertype, and strongly recommending against doing this. It should also suggest considering modifying `Foo` itself, but we have to realize that such decisions tend to be made more on annoyance equilibrium than on correctness.

(I would hope that if the user just changed the `SubFoo.bar()` return type but left the code alone, they would get louder/worse errors for that, as that's the worst case.)

Scenario B: a covariant parameter type. Foo promises to accept null, SubFoo doesn't want to. Perhaps this case is slightly different: SubFoo has the option of just still declaring `@Nullable`, since it's allowed to throw NPE or any other exception for any reason it wants to. However, it still _shouldn't_, because it's withholding useful information from the callers who happen to have the `SubFoo` static type. So I think it works out similarly the Scenario A anyway.

Let's please use standard terminology "weakening" and "strengthening" rather than making up new terms like "contractual requirement" and "backward refinement".

When a subtype specification is weaker than a supertype specification, then the specification is ill-formed. This is one of the few situations where every tool should issue a warning, analogously to writing `@Nullable @NonNull`.

Thanks Mike; that works as an *assertion* of your position, but I've explained *why* I believe it is not ill-formed, so which part of my argument are you disagreeing with?

I don't think the comparison to `@Nullable @NonNull` holds much water; that is a single type at war with itself, literally answering a single question "yes no". Simple "well-formedness" should, I think, be a very low bar, which that still manages not to clear.

I don't see how this case is similar. It is a "bad move" to weaken a supertype contract, but it happens. Given our premise (that the user will not be talked out of their decision to sometimes return null), then the best outcome is for them to annotate their return type nullable. It can be both the best thing for them to do and ill-formed at the same time.

I don't see a need to dictate that tools should warn; I would simply be _surprised_ if they didn't. If I was tempted to dictate anything, it would be "make sure the warning is somehow less severe than if they declare a non-nullable return type but still return null anyway", because I think that's the worst outcome.

This is going to be a contentious discussion in the best of times. And based on my own experience and what I've heard offline from others, I think that some of us bystanders have been confused about _what_ we're discussing here. So I'm going to take a stab at clarifying that.

For starters, we're talking about methods like `Collection.contains(Object)`. But I'll use a slightly different example, `Map.containsKey(Object)` (courtesy @PeteGillin). It makes a good example because at least one well-known overriding method, `ConcurrentHashMap.containsKey(Object)`, throws `NullPointerException` if called with a null value.

Here are some things that I think we all agree on:

1. Some users might like to pass a nullable parameter to the `containsKey` method of an object whose static type is `Map`. Those users might or might not want tools to issue warnings or errors when they do, and we might have our own disagreements about that. My only claim is that some users will ultimately want to have that call in their source code (perhaps with `@SuppressWarnings` applied to it). I contrast this case with...
2. Users definitely never want to pass `null` to the `containsKey` method of an object whose static type is `ConcurrentHashMap`.
3. Given (2), the parameter type for `ConcurrentHashMap.containsKey` that we'd recommend is `@NonNull Object`.
4. Suppose that someone declares `ConcurrentHashMap.containsKey(@NonNull Object)`, as in (3). Now additionally suppose that that person declares **`Map`**`.containsKey` to have a parameter of **`@Nullable`**` Object`. In that case, when tools compile the annotated `ConcurrentHashMap` class, we would recommend issuing some kind of error/warning. This would inform the developer about the mismatch between the parent and child classes' signatures for the method.
5. We also agree on the behavior we'd expect from tools when analyzing both _callers_ and _implementations_ of `containsKey`:
 - Callers of `containsKey(@NonNull Object)` are likely to see warnings/errors if they pass a nullable parameter. (And, if the parameter type is `@Nullable Object` instead, they aren't likely to see warnings/errors.)
 - Implementations of `containsKey(@Nullable Object)` are likely to see warnings/errors if they dereference the parameter without a null check. (And, if the parameter type is `@NonNull Object` instead, they aren't likely to see warnings/errors.)

To summarize all that: However developers annotate these methods, I think we all agree on how tools are likely to respond. (Aside: There is still disagreement about what exactly our spec/docs should _say_ to encourage such behavior without requiring it. But I think that disagreement is mostly unrelated to this current specific issue.)

The disagreement, then, is: How _should_ developers annotate the parameter of `Map.containsKey` -- `@Nullable` or `@NonNull`? Compared to the various things we agree on, this disagreement is either less fundamental or _more_ fundamental:

The argument that it's less fundamental: All we're debating is how we recommend that our users apply annotations. At most, we're debating how we'll apply annotations to `containsKey` specifically when we provide an annotated JDK. This is important, but it's mostly a discussion about what we suggest to users, not what we do in our specification and tools.

The argument that it's more fundamental: What we're really discussing here is the meaning of `@Nullable` (as previously discussed in various places). If we can't tell users when to use our most basic annotation, then how can we feel comfortable telling users _anything_?

I have Opinions on this, but for now, I want to stop and see if this clarified anything for anyone.

(To be clear, we're using `Map` and `CHM` as *examples* here, so don't be distracted by issues that come from their JDKness.)

Your background looks spot on. But I think the question being asked *first* is not what `Map` should do, but rather, *assuming* that `Map` declares the parameter to be nullable, then what should `ConcurrentHashMap` do? And what will motivate it to do that?

I think that non-nullable is the *right* way for it to go, because it is truthful. The specification will appear to violate substitutability because the implementation DOES violate substitutability. Also because for the users who happen to have the specific static type they will get proper behavior. (Of course, an implementer of such a method may mistakenly think they have some kind of assurance that the value can never be null, but that is already wrong anyway, since the caller might not be null-checked code.)

So I'm advocating that we view this as a well-formed expression of contract... which happens to be _bad contract_. The problem report that a user gets should explain the dangers, but the hope is that if the user tried to paper over the problem by just changing the annotation, they should get much scarier sounding errors then.

Then, the question you appear to be asking is, should `Map` have done this at all, if it knows there is even one implementation like this that won't adhere to the contract?

And I think the answer can't be an absolute no (which doesn't erase the problem just discussed anyway). And in real life API owners will probably go whichever route seems to cause the least aggregate aggravation.

I agree that we could further discuss what `CHM` should do if it has to cope with `Map.containsKey(@Nullable)`. My belief, though, is that everyone already agrees on what it should do in that case. Specifically, our position seems to be that `CHM` should define `containsKey(@NonNull)`.

I do think it's logically defensible to take a different position than that, and I invite anyone to do so. If not, that's fine, too: Easy issues are the best issues :) I just want to make sure that:
1. We don't spend a lot of time violently agreeing with one another.
2. We understand where the disagreements that do exist lie.

I have been particularly concerned about (2). On that note: Bystanders, please do speak up if you disagree with anything that I've claimed "everyone" agrees with. I'm not trying to cut off any lines of discussion, only identify the discussions that someone wants to have.

I feel like we're descending into details that are making this question seem complex and specific, but I want to try to establish something more simple and general:

I propose that it's valuable for us to separate the idea of "invalid application of jspecify annotations" from the idea of "valid application of jspecify annotations, which correctly enables tools to see there's some problem in the code".

The impact to the end user might seem slight -- they'd probably see a warning either way, and it might just be worded a little differently -- but I think *we* in this group need to differentiate carefully or it will get too hard to have these discussions.

An example of something that is definitely an invalid usage of jspecify would be annotating a type `@Nullable @NonNull`. There can be no possible reason to allow that. That is ill-formed on its face.

I believe a parameter having some different nullness from its superparameter can never be put in that "ill-formed" bucket, because there is already code out there that is doing this. That code should be annotated truthfully. When it is, those annotations may reveal a deeper problem to tools or they may not. Was a parameter made *less* nullable than its superparameter -- a weaker contract? I expect roughly all tools would want to complain about this; the question we could consider is whether there is value in jspecify "mandating" anything about how they should react. I'm not sure whether there's a need for it.

What if the contract is made stronger (parameter *more* nullable than superparameter)? If we could agree on the above, then the nature of issues like #49 changes a little. It's not about "should we support parameter contravariance?" because that just *is* supported by default. And I would be surprised if any tools cared enough to complain about it (unless it is a specific kotlin incompatibility that motivates them to do so). Seems like they are free to do what they want.

To help make the distinction, maybe we can find words other than "ill-formed" and "valid."

Perhaps what you're proposing is that `@Nullable @NonNull String` _does not express a type_? In contrast, the case here with overrides definitely expresses types, just ones that, taken together, might be questionable in some way.

Would "does not express a type" cover all the cases you're putting in your "invalid application of jspecify annotations" bucket?

That feels like an attempt to nail down exactly where the boundaries lie. That might be too hard to do all at once. I think it's enough if we can agree that the boundary should exist. And in trying to decide which side of that line this particular scenario falls on, some principles may start to emerge. For instance, I've suggested "if there can already exist code for which a certain application of annotations is the most truthful expression possible, then we should never consider that ill-formed".

I've taken a stab at an issue title that asks _whether_ there is a hierarchy of 2 levels of badness, since that seems to be the root issue. Alternatively, if you'd like to keep this issue specifically about which level we put contractual weakening into, we could open a separate issue for the "2 levels" question and then try to resolve that one first.

I'm not sure this is really a question of degree.

The goal of our annotations is to capture small pieces of information from the developer. `@Nullable @NonNull` fails to do this (even if we defined a precedence, it would still fail to be a proper and useful way to express whatever information we defined it to express). No matter how low we define the standard for well-formedness it still shouldn't meet it, because it is like answering a question "yes no". I hope this part is not controversial.

It's hard to debate and settle a question of "is there another kind of badness" per se. What we can do is talk about examples of other problematic scenarios and decide which bucket they fall into. If one by one they all fall into the same total-nonsense bucket then we would eventually say we only needed one category. So far we've discussed one example, and I've explained why it doesn't fit in the same bucket: we would be rendering some existing code impossible to annotate.

Do you want to go through other examples too, or....?

I'm now confused about the buckets. Maybe I'm envisioning that _every_ case that a checker might warn/error about goes into 1 of 2 buckets, while you're talking about only a subset of cases?

The 2 buckets I'm picturing are:

**Bucket 1: "the `@NonNull @Nullable Object` case":**

Possibly `@NonNull @Nullable` is the _only_ thing I see in this bucket currently. I could also imagine including cases like `@Nullable int`, which falls under the umbrella of "structurally illegal" (though that umbrella covers many of things): You were expected to provide either 0 or 1 annotation (or, in the case of `@Nullable int`, you were expected to provide 0), but you provided more.

Maybe the key idea here is that this one single type declaration is wrong in isolation: Even if we know nothing else about any type in the program, we can identify the problem.

**Bucket 2: "type mismatches":**

This is my "everything else" bucket:

- returning `null` from an implementation of `toString()`
- declaring `ImmutableList `
- overriding a method that returns `List ` to return `List `
- etc.

This bucket contains cases in which we applied some type check / conversion / predicate to 2 types, and it failed.

---

I sometimes have gotten the impression that you're picturing a third bucket. It sounds like it might take some things out of my second bucket on the grounds that "we would be rendering some existing code impossible to annotate." I am also confused about the "impossible to annotation" question, but maybe we can get to the bottom of the buckets first?

I feel hopeful that this conversation can get simpler than it has been, somehow. :-)

We don't have to come up with the whole unified theory of buckets right here. Let's just focus on what is well-formed and what isn't. And our guiding star on that, I suggest, is:

"The purpose of our annotations is to capture valid information from the developer (in a reasonable way)."

`@Nullable @NonNull` clearly fails to do this, and `@Nullable @Nullable` is a clearly bad way to do it. These should be considered not well-formed.

I'd like to get this issue back to being just what it started out as, a discussion of whether subtypes can weaken a supertype contract. I argue that this succeeds in capturing valid information from the developer. That valid information allows tools to detect and report a problem, which may be a deeper design issue in the software.

I'll acknowledge that the observable consequence of our decision here _might_ not even be massive. Maybe it's just "six of one". But, if we can't get on the same page conceptually, that seems like ill portent to me. Cmon, we can do this. :-)

My claim is:

1. Code exists, where SuperFoo.bar(Object) promises to accept null but SubFoo.bar(Object) throws on it.
2. This code is problematic because it violates substitutability.
3. Nevertheless, the most correct and useful application of JSpecify annotations to this code is that SuperFoo's parameter is @Nullable and SubFoo's is not.
4. That is accurate, and also provides information that tools can use to report a problem: "'SubFoo.bar(Object)' parameter #1 should be of type '@Nullable Object', because calls to overridden method 'SuperFoo.bar(Object)' will be permitted to pass 'null'."

I believe the point I am making is simple, and I don't see it being _refuted_ either; however it seems as though each response above keeps branching the conversation hither and thither. (Truth be told, I just wanted to get to say "hither and thither".) Can you help me understand what's going on here? :-) Thanks

I'm going to be thinking about this more today, but as a quick response:

The part of that that sits poorly with me is the phrasing "promises to accept null": Yes, we have a method whose parameter type includes null\[*\], but I'm nervous about describing that as a "promise": The method might do _anything_ when given null, including "throw NullPointerException," just as it might do _anything_ when given `1` or `"foo"` or `Color.RED`. Now, the method should _have some defined behavior_ for those inputs. (Or, alternatively, it could explicitly call the behavior unspecified.) But I see that part of the contract as something to explain in Javadoc.

From this point of view, a definitively _non_-null parameter is a way of saying that the behavior of the method on null inputs is undefined. (Analogy: If a method accepts an `Iterable `, its Javadoc doesn't need to talk about what happens if you manage to cram an `Iterable ` into it.) But if the parameter type can include null, then that isn't a "promise" of anything more than (ideally) to _explain_ what the behavior for that input is.

\[*\]: Again, I think that there may be actual controversy over whether the parameter type _does_ include null. I am with you that it does. But I have forgotten the state of the wider conversation on this, so I say that there may be controversy because that's _not_ how the Checker Framework annotates its JDK.

Correct that "promises to accept" is wrong. I reached for that word only to express that when we're annotating an overridable method, we aren't just making a choice for the method's own body, we're making contract that constrains overriders.

Still trying to understand what position I'm arguing against (i.e., where a 'no' to my proposal means we end up). My confused guess at it is "there's no meaningful difference between 'wrong usage of JSpecify' and 'correct usage that highlights a problem', or we just don't need to care, or trying to care would get us into more trouble than it's worth". Is that even it?

[NOTE: my pushing on this is not proportional to its importance to the project. No urgency per se. It is just that *I* don't feel like my mental model is on solid foundations while it's unresolved.]

The following is NOT an actual argument. I'm just disclosing something that I "hope" will end up being the case in most tools. I don't have a guess how relevant it is here.

Suppose we're retrofitting legacy code, and the below is now in null-marked scope:

interface SuperFoo { void bar(@Nullable Object o); }

class SubFoo implements SuperFoo {
 @Override void bar(/*1*/Object o) { ... }
}

We assume most/all tools want to report a problem at 1. Suppose the user thinks "It's saying this is wrong, and I have to add `@Nullable` to fix it", then when they still get a problem reported in the body, they reason "I'm trying not to change things, just annotate, so I'll suppress this for now."

Result: now *no* problem reported at 2 here:

anyClient(SubFoo subfoo) {
 subfoo.bar(/*2*/somethingNullable);
}

And that had represented a real bug, whereas the problem at 1 was "you are doing something super bogus that *risks* real bugs".

I've hoped that the spec will lead tool vendors to recognize these as two quite different cases (if we must say "levels of badness", okay :-)). Because then it's even *possible* that they will surface them in correspondingly different ways (maybe 1 as warning, 2 as error, or whatever).

I'd expect tools very well may report /*2*/, since a nullable argument is
passed to a method declared to expect a non-null parameter. Seemingly it
would be more work not to report something here, and reporting seems better
than not reporting in this case, but ultimately it's a tool decision what
to report in implementation code.

My scenario is that the parameter _had_ been non-null once, but it was changed to nullable in a half-hearted attempt to "make the tools happy".

Note, the scenario is also contrived, and not posed as an argument that "some terrible thing will happen 100,000 times per day to users!". Only illustrating why the conceptual treatment in URL "sits right" with me.

This is what I believed I was addressing when I said:

We may have to say this over and over, "we are not dictating what tools must do. but our choices have consequences on what they will want to do, and that matters."

At this point I feel pretty satisfied just having this be a distinct category of finding, "override conflict" -- distinct from "irrelevant annotation" and from "types not assignable". Does that make this issue resolved?

Having another category of finding sounds eminently inoffensive :)

I imagine that we'll have more to discuss around:

- any user-facing docs about this
- the more general question of whether the _spec_ makes these sorts of distinctions

But it sounds like the high-order bit is the "just" in your proposal: We get most of what we want by calling this "another category" without additionally trying to take positions on whether a particular way of annotating is "correct," what tools should do, etc.?

**Current decision**: JSpecify-compliant tools must be able to recognize when a method that returns a nullable type overrides a method that returns a non-null type (contravariant return) or one that accepts a non-null parameter overrides one that accepts a nullable parameter (contravariant parameters). Tools are free to report those to users at whatever severity they wish, suppressibly or not. When a compliant tool analyzes calls to such methods, the nullability of the method associated with the static type of the receiver should be applied. This approach preserves the ability of compliant tools to be strict or lenient.

**Argument for changing**: Such overriding methods are incorrect, and like Java, JSpecify should consider them invalid and require tools to report them as such.

However, the current decision preserves the ability of tools to report such overriding methods as strictly incorrect, but it does not prevent tools from interpreting such methods in any case.

**Timing**: This must be decided before version 1.0 of the spec.

**Proposal for 1.0: Finalize the current decision.** If you agree, please add a thumbs-up emoji (👍) to this comment. If you disagree, please add a thumbs-down emoji (👎) to this comment and briefly explain your disagreement. Please only add a thumbs-down if you feel you can make a strong case why this decision will be materially worse for users or tool providers than an alternative.

I've made that edit, with some small changes.

1. I removed the reference to a distinct category, since we haven't formalized anything about that.
2. I moved the point about _direct_ supermethods into the main paragraph, and made the second paragraph only about analyzing calls to such methods.

The "distinct category" has been the whole point, so I'm a firm thumbs-down for now.

I have taken "category" to be a well-defined concept _in the conformance tests_ (not that we have a system fully fleshed out, but I think we understand what a different category _means_ there), but there is some ambiguity as to whether we're also talking about things like `@SuppressWarnings` strings. (Presumably we can all agree that we're _not_ saying that a tool has to decide either (a) to report to users every finding of a particular "category" or (b) to not report to users every finding of a particular "category.")

Yes, wonderful! We can refine the category descriptions separately.