Introduce ModelPart to access specific parts of the model from the Service

Generally
Linked classes have been rewritten to match the implementation more closely. In consequence, they are no longer used as intersection type (entity & type & ...) but as separate classes that allow for more specific type definitions (see below "breaking").
ModelPart data structure
The newly introduced type ModelPart<T> effectively allows three types of access:

through iteration: for (const e of service.events) ...
as map of strings to T: service.events['foo.bar']
by function application to narrow it down to specific namespaces: service.events('foo')['bar']

using the third access on ModelParts returns LinkedDefinitions, which only feature access 1 and 2.
Breaking
As getters using ModelPart now return specific portions of the model, users have to account for that in their calls:
- let Foo = model.definitions.Foo
+ let Foo = model.entities.Foo
Foo.name // this is fine either way, as .name is available for all definitions
Foo.keys // as .keys is only available in entities, we need to retrieve it from .entities, not the more general .definitions where not all elements will be entities

Future Work
We currently re-export all linked classes via core.d.ts. We should consider only exposing them from linked.d.ts or linked/classes.d.ts instead (where they are actually defined). We can still put them in their own namespace ("linked"?) and export them bundled from our facade, but we should avoid importing and re-exporting types all over our files to reduce coupling.

@danjoa there are still some open questions I'd like your input on. Specifically if you could comment on the things marked with "TODO:", that would be great. If you find anything else that looks odd, do let me know.


Release PR Version 0.1.5

This PR bumps the version and signals approval to publish a new three-omi update.

Yup, should be good to go 👍


Allow extra provisioning files to be loaded into Grafana

In the ML docker-compose setup we provision a bunch of additional datasources alongside Grafana so we can easily query for data. It'd be very nice to be able to do this when using Tilt too.

This can be done using the datasources sidecar of the Grafana helm chart which is enabled by default. Example looks something like this:
def datasource(name, path):
    datasources = read_yaml(path)
    cm = {
      "apiVersion": "v1",
      "kind": "ConfigMap",
      "metadata": {
        "name": name,
        "labels": {"grafana_datasource": "1"},
      },
      "data": {"datasources.yaml": str(encode_yaml(datasources))},
    }
    k8s_yaml(encode_yaml(cm))

datasource("my-datasources", "/path/to/some/datasource/provisioning/file.yaml")


Sync eng/common directory with azure-sdk-tools for PR 2585

Sync eng/common directory with azure-sdk-tools for PR https://github.com/Azure/azure-sdk-tools/pull/2585  See eng/common workflow

So Green! ✅


Multiple LDAP servers in System --> Access --> Server

Important notices
Before you add a new report, we ask you kindly to acknowledge the following:
[-] I have read the contributing guide lines at https://github.com/opnsense/core/blob/master/CONTRIBUTING.md
Yes
[-] I have searched the existing issues and I'm convinced that mine is new.
Yes
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Not a problem, but feature request
Describe the solution you'd like
A clear and concise description of what you want to happen.
(e.g. I would like an input field in the /ui/firewall/alias which would add .... to ....)
When you go to System: Access: Server and try to add a new LDAP connection to authenticate for OpenVPN and other services, only a single IP address is allowed in the Hostname | IP address field.
Is it possible to add multiple addresses? In most LDAP environment, there are usually 2 servers.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
I am currently using a single IP address to authenticate against Windows Active Directory server.
Additional context
Add any other context or screenshots about the feature request here.

You can do this via HAProxy: https://www.routerperformance.net/opnsense-bypass-ldaps-errors-via-haproxy/
HAProxy also has very good health checking so you can balance or failover for multiple DCs

Shouldn't it be possible to add another authentication server to OPNSense, and basically mirror all settings except for the server name or IP? I'm playing around with the most recent release and it looks like it allows you to select multiple authentication sources for an OpenVPN server. So just tick them both and profit?

Shouldn't it be possible to add another authentication server to OPNSense, and basically mirror all settings except for the server name or IP? I'm playing around with the most recent release and it looks like it allows you to select multiple authentication sources for an OpenVPN server. So just tick them both and profit?

This works. You can create multiple authentication server, then use all when setting up OpenVPN.


recurring events

At first, thanks for this awesome and well-maintained library!
Do you plan to add rrule (recurrence) support? Theoretically, would it be possible to specify recurrence rule for google/microsoft/yahoo calendar by URL? (I know the Ics Calendar format does support it)
I found Google calendar render URL support recurrence:  Pass a URL-encoded RRULE or RDATE property with value (e.g., a URL-encoded version of RRULE:FREQ=MONTHLY;BYDAY=2SU would repeat monthly on the second Sunday) via the recur parameter to set recurring events. Tested and it still works. (source)
Thanks,
Balazs

This is a great idea. I'll aim to implement this in the near future (possibly targeting the next minor release).

Just sent over a pull request on a first cut at recurrence (ics).

Thanks @eugenedw for your contribution!
Recurrence support is now fully implemented in v1.3.5 for the calendar services that support it. You can now use the following angular attributes for recurring events:
| recurrence-frequency | Event frequency; DAILY, WEEKLY, MONTHLY, YEARLY                                            | Enum              | No        | DAILY              |
| recurrence-interval  | Time between recurrences                                                                           | Integer           | No        | 2                  |
| recurrence-count     | Number of times the event should repeat                                                            | Integer           | No        | 4                  |
| recurrence-end       | Date when the last recurrence should occur                                                         | String date       | Yes*      | 20190904T210000    |
| recurrence-weekstart | Day that the week starts on (default: SU); SU MO, TU, WE, TH, FR, SA               | Enum              | No        | SU                 |
| recurrence-weekdays  | Comma-separated days of the week that the event occurs on; SU MO, TU, WE, TH, FR, SA | Enum              | No        | TU,TH,SA           |
| recurrence-monthdays | Comma-separated list of monthdays                                                                  | String of numbers | No        | 2,4,6,8            |


Providing missing accessor to EVP_PKEY.engine

The accessor to the engine field of EVP_PKEY structure was missing on making internal structures opaque. This patch is designed to provide it and documentation.
Backport to 1.1.1 of the #8329
Checklist

[x] documentation is added or updated

Pushed. Thanks.


ICUE does not identify.

Was using version 0.3.0, was working everything right identified in the application. I ended up getting a new arduino, I went to the version 0.4.0 in the new arduino and without wanting to finish what was working. now it does not identify anymore in the icue, if a mute the PID = 0c0b for PID = 0c0c it appears only that it is the same as the image. and in the new arduino the same thing.

Which arduino, iCUE version, OS?
Do you have to arduinos connected at the same time?
Which sketch did you used?
Why you not using the Issue Tech-support template?
PS: you can include images natively in GitHub no need for file hoster

ICUE version: 3.17.94. Windows 10.
only one connected arduino.

cLNP.begin(); is missing in the setup method.

https://github.com/Legion2/CorsairLightingProtocol/blob/v0.4.0/examples/LightingNodePRO/LightingNodePRO.ino#L31 this is the example sketch for v0.4.0, you are using the example sketch of dev (v0.5.0).

now v0.5.0 is release so, this sketch should work with the library from the library manager.


Does rebar3 support {erl_first_files, ...} configuration directive?

I'm trying to compile my project with rebar3

$ ./rebar3 -v
rebar 3.0.0-alpha-5 on Erlang/OTP 17 Erts 6.4

The main question is how to compile behavior definition or parse_transform modules first?
For now it fails with

"_build/default/lib/my_lib/src/a.erl:2: behaviour my_behavior undefined"

Further attempts to build with no success:

$ ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> When submitting a bug report, please include the output of rebar3 report "your command"
$ DEBUG=1 ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> Uncaught error: function_clause
===> When submitting a bug report, please include the output of rebar3 report "your command"

How can I get more detailed output for this failure?

Could you show your project structure (for example output of tree command) and your rebar.config, please?

This is odd since the compiler should inspect the modules and find that a parse_transform or behaviour is needed to build and compile those first.

Well, I've tested it with a simple project structure like this and everything seems ok
$ tree
.
├── apps
│   └── my_lib
│       ├── ebin
│       ├── rebar
│       ├── rebar.config
│       └── src
│           ├── my_behavior.erl
│           ├── my_behavior_http.erl
│           ├── my_lib.app.src
│           └── my_lib.erl
├── _build
│   └── default
│       └── lib
│           ├── my_lib
│           │   ├── ebin
│           │   │   └── my_lib.app
│           │   ├── include -> ../../../../apps/my_lib/include
│           │   ├── priv -> ../../../../apps/my_lib/priv
│           │   ├── src -> ../../../../apps/my_lib/src
│           │   └── test -> ../../../../apps/my_lib/test
│           └── rebar3test
│               ├── ebin
│               │   ├── rebar3test.app
│               │   ├── rebar3test_app.beam
│               │   └── rebar3test_sup.beam
│               ├── include -> ../../../../include
│               ├── priv -> ../../../../priv
│               ├── src -> ../../../../src
│               └── test -> ../../../../test
├── ebin
├── rebar
├── rebar3
├── rebar.config
├── rebar.lock
└── src
    ├── rebar3test_app.erl
    ├── rebar3test.app.src
    └── rebar3test_sup.erl

With {erl_first_files, ["src/my_behavior.erl"]} in the rebar.config it compiles ok
I suggest there is a behavior in my real project I forgot to add to erl_first_files
Also I've found messages like Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace caused by dependencies without rebar.config in a source tree. Probably the solution is to test this file exists and notify with more informative message? Or just act as original rebar and assume no options if config is missing

Oh, forgot the contents of rebar.config in my test project
{erl_first_files, ["src/my_behavior.erl"]}.
{erl_opts, [debug_info, warnings_as_errors]}.
{cover_enabled, true}.

And here's the dependency which causes rebar3 failure: https://github.com/maxlapshin/luerl

It is probably unrelated, but why do you have a top level src and apps dir? And are there beam files in that top level ebin dir?

Oh, I see, ebin just has the .app file. I've checked out luerl and I am investigating.

Also, is that rebar.config content under apps/my_lib/rebar.config?

Oh, the issue is the .app file is wrong (right?) it can't have .erl in an atom that isn't single quoted.

It is probably unrelated, but why do you have a top level src and apps dir? And are there beam files in that top level ebin dir?

Well, I'm using such structure for small projects. Usually there's just a launcher inside src dir. Top level ebin dirs are there because I tried to build it with old rebar. They are empty

Also, is that rebar.config content under apps/my_lib/rebar.config?

Correct. The toplevel config is simple {lib_dirs, ["apps"]}. {sub_dirs, ["apps/my_lib"]}.
I've really found an error in my production rebar.config (misspelled filename of the behavior definition), so the subject of this issue is resolved for me, thank you!
And I suggest the only question is notifying about missing rebar.config when trying to build deps?

It is valid for dependencies not to have a rebar.config file, if for example, they have no dependencies of their own and are otherwise content with default values everywhere.

Agree. I've fixed this dep for me just by forking it and adding config

Wait, I'm confused. What rebar.config did you add? What contents?

Finally I've found a minimal example of strange behavior https://github.com/asskovalev/rebar3test.git
[~/devel/rebar3test]$ rm -rf _build rebar.lock
[~/devel/rebar3test]$ ./rebar3 compile
===> Verifying dependencies...
===> Fetching luerl ({git,"git://github.com/asskovalev/luerl.git"})
===> WARNING: It is recommended to use {branch, Name}, {tag, Tag} or {ref, Ref}, otherwise updating the dep may not work as expected.
===> Fetching test_behavior ({git,
                                     "git://github.com/asskovalev/test_behavior.git"})
===> WARNING: It is recommended to use {branch, Name}, {tag, Tag} or {ref, Ref}, otherwise updating the dep may not work as expected.
===> Compiling test_behavior
===> Compiling /home/kovalev/devel/rebar3test/_build/default/lib/test_behavior/src/my_behavior_http.erl failed
/home/kovalev/devel/rebar3test/_build/default/lib/test_behavior/src/my_behavior_http.erl:2: behaviour my_behavior undefined

[~/devel/rebar3test]$ ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> When submitting a bug report, please include the output of `rebar3 report "your command"`

Here I'm trying to uncomment the correct build order in the _build/default/lib/test_behavior/rebar.config
[~/devel/rebar3test]$ ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> When submitting a bug report, please include the output of `rebar3 report "your command"`

And also remove dependency 'test_behavior' in the top level rebar.config
[~/devel/rebar3test]$ ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> When submitting a bug report, please include the output of `rebar3 report "your command"`

Removing entire dependency. Still no success
[~/devel/rebar3test]$ rm -rf _build/default/lib/test_behavior
[~/devel/rebar3test]$ ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> When submitting a bug report, please include the output of `rebar3 report "your command"`

Cleaning lock file
[~/devel/rebar3test]$ rm rebar.lock
[~/devel/rebar3test]$ ./rebar3 compile
===> Verifying dependencies...
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace
===> When submitting a bug report, please include the output of `rebar3 report "your command"`

The only way is to fix test_behavior's repo, push it, remove rebar.lock and _build directories and then build succedes. Am I doing something wrong? As for me this is strange to clean all the dependencies if only one is broken

What do you mean "fix test_behavior's repo"? For me this fails to build because luerl has a bad .app file.

Note that I've added error messages for what is wrong with luerl to make this easier in the future: https://github.com/rebar/rebar3/pull/470

Try to build it with two deps at toplevel config as in my repo
Then remove test_behavior from deps, clean lockfile and _build dir, build again
And compare _build/default/lib/luerl/ebin/luerl.app in theese two cases
As for me, the first case results in incorrect .app file:
{application, luerl,
 [
  {description, "Luerl - an implementation of Lua on Erlang"},
  {vsn, "1"},
  {modules,[luerl.erl,
	    luerl_app.erl,
	    luerl_comp.erl,
	    luerl_comp_cg.erl,
	    luerl_comp_env.erl,
	    luerl_comp_locf.erl,
	    luerl_comp_peep.erl,
	    luerl_comp_vars.erl,
	    luerl_emul.erl,
	    luerl_lib.erl,
	    luerl_lib_basic.erl,
	    luerl_lib_io.erl,
	    luerl_lib_math.erl,
	    luerl_lib_os.erl,
	    luerl_lib_package.erl,
	    luerl_lib_string.erl,
	    luerl_lib_string_format.erl,
	    luerl_parse.yrl,
	    luerl_scan.xrl,
	    luerl_sup.erl,
	    ttdict.erl
	    ]},
  {registered, []},
  {applications, [
                  kernel,
                  stdlib,
		  compiler,
		  parsetools
                 ]},
  {mod, {luerl_app, []}},
  {env, []}
 ]}.

And the second one produces correct file:
{application,luerl,
             [{description,"Luerl - an implementation of Lua on Erlang"},
              {vsn,"1"},
              {registered,[]},
              {applications,[kernel,stdlib]},
              {mod,{luerl_app,[]}},
              {env,[]},
              {modules,[luerl,luerl_app,luerl_comp,luerl_comp_cg,
                        luerl_comp_env,luerl_comp_locf,luerl_comp_peep,
                        luerl_comp_vars,luerl_emul,luerl_lib,luerl_lib_basic,
                        luerl_lib_bit32,luerl_lib_io,luerl_lib_math,
                        luerl_lib_os,luerl_lib_package,luerl_lib_string,
                        luerl_lib_string_format,luerl_lib_table,luerl_parse,
                        luerl_scan,luerl_sup,ttdict]}]}.

Note that I've added error messages for what is wrong with luerl to make this easier in the future: #470
That's great!

Ooooh, facepalm, luerl has a .app AND a .app.src file. That is what is causing the confusion. I'll see why it doesn't overwrite the .app in the first run.

Oh! I've misunderstand you when you was talking about .app file inside leurl/ebin
This file is really exist. Sorry for wasting time, but this case was really hard to diagnose for me

No worries, it is a funky bug. I think we should always overwrite .app if a .app.src file exists and ignore the original .app. I'm working on fixing that.

Will reopen until that is fixed.

Why did you close again? The fix is here https://github.com/rebar/rebar3/pull/471

Got confused, I guess

Now the fix is merged and I think we can close this?


[release-v0.17.x] tekton: port koparse fix to release-0.17.x

Changes
Without porting those fixes to the release branch, we cannot do a
release 😅
Signed-off-by: Vincent Demeester<EMAIL_ADDRESS>/kind misc
/cc @afrittoli @bobcatfish @sbwsg
Submitter Checklist
These are the criteria that every PR should meet, please check them off as you
review them:

[x] Includes tests (if functionality changed/added)
[ ] Includes docs (if user facing)
[x] Commit messages follow commit message best practices
[x] Release notes block has been filled in or deleted (only if no user facing changes)

See the contribution guide for more details.
Double check this list of stuff that's easy to miss:

If you are adding a new binary/image to the cmd dir, please update
the release Task to build and release this image.

Reviewer Notes
If API changes are included, additive changes must be approved by at least two OWNERS and backwards incompatible changes must be approved by more than 50% of the OWNERS, and they must first be added in a backwards compatible way.
Release Notes
Ports fixes for koparse.py script from master to the v0.17.x release branch

/retest


Script does not find the folder D

Hi,
here is the powershell script that i have created and launched :
$SetupDatabaseScript = @'
if ($restartingInstance) {
    # Do nothing on restart
} else {
    $databaseFolder = "D:\Database"
    Write-Host "Using $databaseFolder as new location for database files"

    $mdfName = Join-Path $databaseFolder "$DatabaseName.mdf"
    $ldfName = Join-Path $databaseFolder "$DatabaseName.ldf"
    $filesExists = (Test-Path $mdfName -PathType Leaf) -and (Test-Path $ldfName -PathType Leaf)

    Write-Host "Take database [$DatabaseName] offline"
    Invoke-SqlCmd -Query "ALTER DATABASE [$DatabaseName] SET OFFLINE WITH ROLLBACK IMMEDIATE"

    if ($filesExists) {
        Write-Host "Database files for [$DatabaseName] already exists"
    } else {
        Write-Host "Move database files for [$DatabaseName]"
        (Invoke-SqlCmd -Query "SELECT Physical_Name as filename FROM sys.master_files WHERE DB_NAME(database_id) = '$DatabaseName'").filename | ForEach-Object {
            $FileInfo = Get-Item -Path $_
            $DestinationFile = "{0}\{1}{2}" -f $databaseFolder, $DatabaseName, $FileInfo.Extension
            if (($DestinationFile -ne $mdfName) -and ($destinationFile -ne $ldfName)) { throw "Unexpected filename: $DestinationFile" }
            Copy-Item -Path $FileInfo.FullName -Destination $DestinationFile -Force
        }
    }

    Write-Host "Drop database [$DatabaseName]"
    Invoke-SqlCmd -Query "DROP DATABASE [$DatabaseName]"

    $Files = "(FILENAME = N'$mdfName'), (FILENAME = N'$ldfName')"
    Write-Host "Attach files as new Database [$DatabaseName]"
    Invoke-SqlCmd -Query "CREATE DATABASE [$DatabaseName] ON (FILENAME = N'$mdfName'), (FILENAME = N'$ldfName') FOR ATTACH"
}
'@

#$additionalParameters = @("-v c:\temp\navdbfiles:c:\navdbfiles")
#New-NavContainer #-accept_eula `
                 #"-containerName "test" `
                 #-auth NavUserPassword `
                 #-imageName "microsoft/dynamics-nav" `
                 #-additionalParameters $additionalParameters `
                 #-myScripts @{"SetupDatabase.ps1" = $SetupDatabaseScript }

                New-NavContainer -accept_eula `
                 -accept_outdated `
                 -enableSymbolLoading `
                 -includeCSide ServerName `
                 -licenseFile "C:\Users\vmadmin\Documents\Licence 2018.flf" `
                 -doNotExportObjectsToText `
                 -bakFile "C:\Users\vmadmin\Downloads\Name_backup_2019_09_04_032117_4876990\Name_backup_2019_09_04_032117_4876990.bak" `
                 -myScripts @{"SetupDatabase.ps1" = $SetupDatabaseScript}

and the error :
NavContainerHelper is version <IP_ADDRESS>
Host is Microsoft Windows Server 2019 Datacenter - ltsc2019
Docker Client Version is 19.03.1
Docker Server Version is 19.03.1
Using image mcr.microsoft.com/dynamicsnav:2018-cu6-fr-ltsc2019
Removing container BCSAAS
Removing C:\ProgramData\NavContainerHelper\Extensions\BCSAAS
Creating Container BCSAAS
Using license file C:\Users\vmadmin\Documents\Licence 2018.flf
Version: 11.0.22292.0-fr
Generic Tag: <IP_ADDRESS>
Container OS Version: 10.0.17763.316 (ltsc2019)
Host OS Version: 10.0.17763.737 (ltsc2019)
WARNING: The container operating system matches the host operating system, but the revision is different.
If you encounter issues, you might want to specify -isolation hyperv
Using locale fr-FR
Using process isolation
Disabling the standard eventlog dump to container log every 2 seconds (use -dumpEventLog to enable)
Files in C:\ProgramData\NavContainerHelper\Extensions\BCSAAS\my:

AdditionalSetup.ps1
license.flf
MainLoop.ps1
SetupDatabase.ps1
SetupWebClient.ps1
Creating container BCSAAS from image mcr.microsoft.com/dynamicsnav:2018-cu6-fr-ltsc2019
da1f8b32b587c701b7ab839abc97267d119ce7bc03caae48a778427106c158e6
Waiting for container BCSAAS to be ready
Initializing...
Starting Container
Hostname is BCSAAS
PublicDnsName is BCSAAS
Using Windows Authentication
Starting Local SQL Server
Starting Internet Information Server
Using D:\Database as new location for database files
Cannot find drive. A drive with the name 'D' does not exist.
at , C:\Run\my\SetupDatabase.ps1: line 7
at , C:\Run\navstart.ps1: line 108
at , C:\Run\start.ps1: line 121
at , : line 1Error
Initializing...
Starting Container
Hostname is BCSAAS
PublicDnsName is BCSAAS
Using Windows Authentication
Starting Local SQL Server
Starting Internet Information Server
Using D:\Database as new location for database files
Cannot find drive. A drive with the name 'D' does not exist.
at , C:\Run\my\SetupDatabase.ps1: line 7
at , C:\Run\navstart.ps1: line 108
at , C:\Run\start.ps1: line 121
at , : line 1
Initialization of container BCSAAS failed
At C:\Program Files\WindowsPowerShell\Modules\navcontainerhelper\<IP_ADDRESS>\ContainerHandling\Wait-NavContainerReady.ps1:45 char:17

...             throw "Initialization of container $containerName failed" ...

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

CategoryInfo          : OperationStopped: (Initialization ...INBCSAAS failed:String) [], RuntimeException
FullyQualifiedErrorId : Initialization of container BCSAAS failed

Thanx for help.

When running the setupdatabase.ps1 - it executes inside the container and cannot see the host.
In the container, there is nothing called d:\databases.

ok clear.
My initial issue was that i have no more space in c:\ folder to restore a 60 Gb customer database. So i can't restore the backup file
How can i change the folder where the database is created when the container is created ?
Or how can i do something else to do this ?

I think you can share d:\somefolder to a folder in the container and use that.

You cannot restore a DB larger then 10gb since the image uses sqlexpress.
For this reason we use sql server instances on the host in our team. It works great but you have to do some configuration to make it reliable. For example you have to tell docker to use a fixed ip range for its nat network since hostname resolution does not work (at least i did not get it working). So you can use the gateway ip address (which is your host) as sql server name.
Btw i would suggest to use sql server developer edition in the image. That would give us more flexibility

Ok thanks for your feedback.
I tried to add this to the above ²script :
$additionalParameters = @("-v d:database:c:\navdbfiles")
New-NavContainer -accept_eula                      -accept_outdated
-enableSymbolLoading                      -includeCSide
-doNotExportObjectsToText                      -bakFile "C:\Users\vmadmin\Downloads\backup_2019_09_04_032117_4876990\backup_2019_09_04_032117_4876990.bak"
-additionalParameters $additionalParameters `
-myScripts @{"SetupDatabase.ps1" = $SetupDatabaseScript}
And i have the following error message :
cmdlet New-NavContainer at command pipeline position 1
Supply values for the following parameters:
containerName: STEVEN
NavContainerHelper is version <IP_ADDRESS>
Host is Microsoft Windows Server 2019 Datacenter - ltsc2019
Docker Client Version is 19.03.1
Docker Server Version is 19.03.1
Using image mcr.microsoft.com/dynamicsnav:2018-cu6-fr-ltsc2019
Creating Container STEVEN
Version: 11.0.22292.0-fr
Generic Tag: <IP_ADDRESS>
Container OS Version: 10.0.17763.316 (ltsc2019)
Host OS Version: 10.0.17763.737 (ltsc2019)
WARNING: The container operating system matches the host operating system, but the revision is different.
If you encounter issues, you might want to specify -isolation hyperv
Using locale fr-FR
Using process isolation
Disabling the standard eventlog dump to container log every 2 seconds (use -dumpEventLog to enable)
Files in C:\ProgramData\NavContainerHelper\Extensions\STEVEN\my:

AdditionalSetup.ps1
MainLoop.ps1
SetupDatabase.ps1
SetupWebClient.ps1
Creating container STEVEN from image mcr.microsoft.com/dynamicsnav:2018-cu6-fr-ltsc2019
ce004859581a62fbea9b4ad918187b4b7a51367bc2c1d2dc3a530994f9e23d1f
Waiting for container STEVEN to be ready
Initializing...
Starting Container
Hostname is STEVEN
PublicDnsName is STEVEN
Using Windows Authentication
Starting Local SQL Server
Starting Internet Information Server
Modifying Service Tier Config File with Instance Specific Settings
Starting Service Tier
Registering event sources
Creating DotNetCore Web Server Instance
Creating http download site
Creating Windows user vmadmin
Setting SA Password and enabling SA
Creating SUPER user
ServerInstance 'MicrosoftDynamicsNavServer$NAV' is not running.
at , C:\Run\SetupNavUsers.ps1: line 13
at , C:\Run\navstart.ps1: line 174
at , C:\Run\start.ps1: line 121
at , : line 1Error
Initializing...
Starting Container
Hostname is STEVEN
PublicDnsName is STEVEN
Using Windows Authentication
Starting Local SQL Server
Starting Internet Information Server
Modifying Service Tier Config File with Instance Specific Settings
Starting Service Tier
Registering event sources
Creating DotNetCore Web Server Instance
Creating http download site
Creating Windows user vmadmin
Setting SA Password and enabling SA
Creating SUPER user
ServerInstance 'MicrosoftDynamicsNavServer$NAV' is not running.
at , C:\Run\SetupNavUsers.ps1: line 13
at , C:\Run\navstart.ps1: line 174
at , C:\Run\start.ps1: line 121
at , : line 1
Initialization of container STEVEN failed
At C:\Program Files\WindowsPowerShell\Modules\navcontainerhelper\<IP_ADDRESS>\ContainerHandling\Wait-NavContainerReady.ps1:45 char:17

...             throw "Initialization of container $containerName failed" ...

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

CategoryInfo          : OperationStopped: (Initialization ...r STEVEN failed:String) [], RuntimeException
FullyQualifiedErrorId : Initialization of container STEVEN failed

I did not understand the error message.
Please Help

Any idea ?

If your database has the size you mentioned - then I guess i wont work as Marknitek states.
Why don't you restore the database to a SQL server and just run the container using that database.
That would be much easier - and easier for you to troubleshoot.
Or if your database is less than 10G - start the container standard (no script overrides) and restore the database afterwards, either using restore-databaseinNavcontainer or SQL Server Management Studio.
The error you get is that the service tier doesn't start - and that can be caused by a million things, by manually restoring and mounting you might have a better chance to troubleshoot..

I tried to restore the SQL database on the database server of my VM => it works !
but when i ran the following script to test the SQL Connection from docker, i have the following message :

script :
docker run -it --name sqlconnectiontest mcr.microsoft.com/dynamicsnav:2018-cu6-fr-ltsc2019 powershell -command "Invoke-Sqlcmd -ServerInstance '$databaseServerInstance' -Username '$($databaseCredential.Username)' -Password '$dbPassword' -Database '$databaseName' -Query 'SELECT COUNT(*) FROM [dbo].[User]'"

Error message :
]0;C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe  ]0;Administrator: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Invoke-
Sqlcmd : A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or was not
accessible. Verify that the instance name is correct and that SQL Server is
configured to allow remote connections. (provider: Named Pipes Provider,
error: 40 - Could not open a connection to SQL Server)
At line:1 char:1

Invoke-Sqlcmd -ServerInstance 'NAV2018CU6' -Username 'sbale' -Passwor ...

  + CategoryInfo          : InvalidOperation: (:) [Invoke-Sqlcmd], SqlExcept
 ion

    + FullyQualifiedErrorId : SqlExectionError,Microsoft.SqlServer.Management.
PowerShell.GetScriptCommand

Invoke-Sqlcmd :
At line:1 char:1

Invoke-Sqlcmd -ServerInstance 'NAV2018CU6' -Username 'sbale' -Passwor ...

  + CategoryInfo          : ParserError: (:) [Invoke-Sqlcmd], ParserExceptio
 n
  + FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Ma
 nagement.PowerShell.GetScriptCommand

I
And finally when i tried to create a new container using new-navcontainer for this database, i have the following error message :
Cannot establish a connection to the SQL Server/Database.
This could be due to one of the following reasons:

SQL Server is not started.
The database does not exist.
Proper permissions have not been given to the NAV Server Account.

Try again later or contact your system administrator.
at , C:\Run\SetupDatabase.ps1: line 122
at , C:\Run\navstart.ps1: line 108
at , C:\Run\start.ps1: line 121
at , : line 1
Initialization of container test failed
At C:\Program Files\WindowsPowerShell\Modules\navcontainerhelper\<IP_ADDRESS>\ContainerHandling\Wait-NavContainerReady.ps1:45 char:17

...             throw "Initialization of container $containerName failed" ...

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

CategoryInfo          : OperationStopped: (Initialization of container test failed:String) [], RuntimeException
FullyQualifiedErrorId : Initialization of container test failed

Script :
New-NavContainer -accept_eula                  -containerName "test"
-Auth NavUserPassword                  -imageName $imageName
-Credential $navcredential                  -databaseServer $databaseServer
-databaseInstance $databaseInstance                  -databaseName $databaseName
-databaseCredential $databaseCredential `
-accept_outdated

Or I tried to use the navserver container and change the server configuration to connect to my database but the service run but i cannot connect to windows client or web client.
Someone can help ?

Is this a different problem then what this thread started out with?
Instead of trying to do everything during startup - why not start the container with the standard database - and then use Invoke-ScriptInBCContainer to restore and setup the second database - and then switch config settings + restart service tier at the end.

ok.
What script do i suppose to use in this command ?
The script I use in my comments .
my database has a siez of 60 gb.

It's confusing because you are hijacking one issue and continue with a second issue - it is hard to figure out what is the issue now.
but... - If you have restored your database to a SQL Server somewhere - then you should be able to configure the service tier in the container in exactly the same way as you would do if you are running an onprem installation.

SQL EXPRESS inside the container can maximum be 10GB - you would need to restore your database to a "real" SQL Server and then connect a container to that SQL Server when using docker.

I tried it but I cannot start the nav Server because the navserver in the container cannot see the sql database.
Do you have some procedures or walkthrough ?

Placing the database on the host isn't easy - the container cannot see the host. Either you need to place it on another database server or you need to make the host visible from docker.

ok. For the moment, i place it on another database server. But How do i made the host visible from docker ?

For docker - the host is just like any other computer in the network.
So if your host can be reached (like the foreign database server) - then docker should also be able to see it.

ok. thank you for your help


New trait: core::convert::IntoUnderlying

This adds a trait to allow conversions from enums with a primitive
representation to their primitive representation.
This spun out of the related https://github.com/rust-lang/rfcs/pull/3040.
Rendered

/// This trait should only be implemented where conversion is trivial; for non-trivial conversions,
/// prefer to implement [`Into`].
pub trait IntoUnderlying {
    type Underlying;
    fn into_underlying(self) -> Self::Underlying;
}

That "should" got me thinking.  How important is it?  To explore:

It's not actually any more important than in From.  Then it's kinda like trait IntoUnderlying : Into<Self::Underlying> { type Underlying; }.

It's very important, and we want people to be able to rely on it.  Then it's like unsafe trait IntoUnderlying { type Underlying; }, but that's very much like the "archetype" idea from safe transmute.  So it could also be thought of as trait IntoUnderlying : safe_transmute::MuckableInto<Self::Underlying> { type Underlying; }.

But I guess both of those lose the "method that doesn't need type annotations" part of the proposal.  I think think it's interesting, though.  Maybe there's a way to combine them?  Sketch of an undeveloped idea:
pub trait Wrapper {
    type Underlying;
    fn into_underlying(self) -> Self::Underlying
        where Self: Into<Self::Underlying>
    {
        self.into()
    }
    fn from_underlying(x: Self::Underlying) -> Self
        where Self::Underlying: Into<Self>
    {
        x.into()
    }
    fn try_into_underlying(self) -> Result<Self::Underlying, Self::Error>
        where Self: TryInto<Self::Underlying>
    {
        self.try_into()
    }
    fn try_from_underlying(x: Self::Underlying) -> Result<Self, Self::Underlying::Error>
        where Self::Underlying: TryInto<Self>
    {
        x.try_into()
    }
}

So that there'd never be a reason to implement this directly.  That does still have derive problems, though.

/// This trait should only be implemented where conversion is trivial; for non-trivial conversions,
/// prefer to implement [`Into`].
pub trait IntoUnderlying {
    type Underlying;
    fn into_underlying(self) -> Self::Underlying;
}

That "should" got me thinking. How important is it? To explore:

It's not actually any more important than in From.  Then it's kinda like trait IntoUnderlying : Into<Self::Underlying> { type Underlying; }.

I think it's not super important, but there is value in having what is effectively a marker trait to show the conversion is expected to be ~free. Maybe there should be a marker trait for Into (akin the relationship between Clone and Copy), something like TrivialInto, which shows that the conversion is trivial? Though maybe that's in practice just const Into vs Into... That said:

It's very important, and we want people to be able to rely on it.  Then it's like unsafe trait IntoUnderlying { type Underlying; }, but that's very much like the "archetype" idea from safe transmute.  So it could also be thought of as trait IntoUnderlying : safe_transmute::MuckableInto<Self::Underlying> { type Underlying; }.

I hadn't read up on the safer transmute work, but now that I have, I think this is exactly equivalent to what in an earlier version of the RFC was:
#[derive(PromiseTransmutableInto)]
#[repr(u8)]
enum Number {
    Zero,
    One,
}

fn main() {
    let n: u8 = Number::Zero.transmute_into();
    assert_eq!(n, 0_u8);
}

which is nicely more general.
Per the current RFC, I think we'd want Number: IntoUnderlying<Underlying=u8> to imply u8: TransmuteFrom<Number> which seems like a reasonable blanket impl. Unless I'm missing something, the RFC doesn't currently provide a TransmuteInto trait, but it feels like:
#[derive(TransmutableInto)]
#[repr(u8)]
enum Number {
    Zero,
    One,
}

would be a reasonable derive, and would obviate the need for IntoUnderlying - TransmutableInto feels less general than Into enough to not need the repr type to be named in the derive. @jswrenn do you have thoughts, both on this general proposal, and a guess as to the near-term future of #2981?

But I guess both of those lose the "method that doesn't need type annotations" part of the proposal. I think think it's interesting, though. Maybe there's a way to combine them? Sketch of an undeveloped idea:
pub trait Wrapper {
    type Underlying;
    fn into_underlying(self) -> Self::Underlying
        where Self: Into<Self::Underlying>
    {
        self.into()
    }
    fn from_underlying(x: Self::Underlying) -> Self
        where Self::Underlying: Into<Self>
    {
        x.into()
    }
    fn try_into_underlying(self) -> Result<Self::Underlying, Self::Error>
        where Self: TryInto<Self::Underlying>
    {
        self.try_into()
    }
    fn try_from_underlying(x: Self::Underlying) -> Result<Self, Self::Underlying::Error>
        where Self::Underlying: TryInto<Self>
    {
        x.try_into()
    }
}

So that there'd never be a reason to implement this directly. That does still have derive problems, though.

I think this is an interesting thing to consider, but as you note, we'd still need some way of indicating the derive, with or without this mechanism, at which point I feel like this would be an interesting layer, but probably something to contemplate alongside/after, rather than instead...
One thing on naming worth noting is that I'm somewhat wary of the term "wrapper" - I think there are two importantly distinct concepts here; a wrapping type and a transmutable type. A primitive-repr'd enum doesn't wrap a number, it is represented by a number. An Rc or a BufWriter wraps a value, but itself isn't transmutable into one. The grey areas are newtypes (where I'd say a #[repr(transparent)] newtype can be considered to do either, and a non-#[repr(transparent)] newtype is less clear). So if we were going down that path, I'd suggest Equivalent, Convertible, Interchangeable or similar, rather than Wrapper.

Thanks for pushing on this! Rather than trying to abstract over newtypes and enums, might I suggest a slightly more limited/gradual approach?
A Gradual Approach to Enum Discriminant Reform
Enums are tricky. For instance, although all enums have a discriminant type, that type isn't necessarily the same type used for storing the in-memory tag. And, although all variants have a logical discriminant, you can't necessarily access it using as. (There are also all sorts of issues with our existing vocabulary for talking about these intricacies.)
1. Referring to the Discriminant Type
Since all enums have a discriminant type, let's consider starting there, with just this compiler-intrinsic (i.e., automatically implemented + sealed) trait:
#[lang = "enum_trait"]
pub trait Enum {
    //// The discriminant type of the enum.
    type Discriminant;
}

With this, I can use as without shooting myself in the foot. Instead of writing:
enum Foo { Bar, Baz }

Foo::Bar as someprimitivetype

...I'd instead write:
Foo::Bar as Foo::Discriminant

With this associated type, the foot-gunny Foo::Bar as someprimitivetype form could be linted for and perhaps even be deprecated.
2. Uniform Discriminant Access
Although all variants have a logical discriminant, you can't necessarily access it using as. For instance:
enum Foo {
    Bar(),
    Baz,
}

assert_eq!(Foo::Baz as isize, 1);

The discriminant of Bar is 0. We know this because the discriminant of Baz is 1, because the discriminant of a variant, if unset, is specified to be equal to one plus the discriminant of the previous variant. But, if I try Foo::Bar as isize, I don't get 1, I get the result of casting a function pointer to an isize. (Footgun!)
If we add a field to Bar, we can't as cast Baz at all:
#![feature(arbitrary_enum_discriminant, never_type)]

#[repr(u8)]
enum Foo {
    Bar(!) = 42,
    Baz, // discriminant/tag is 43
}

let _ = Foo::Baz as u8; // error[E0605]: non-primitive cast: `Foo` as `u8`

Let's fix this. Since all enum variants arguably have a logical discriminant, let's extend our trait with a method to retrieve it:
#[lang = "enum_trait"]
pub trait Enum {
    //// The discriminant type of the enum.
    type Discriminant;

    /// Produces the discriminant of the given enum variant.
    fn discriminant(&self) -> Self::Discriminant { ... }
}

With this method, as can be altogether discouraged/deprecated as a mechanism for retrieving the discriminant of an enum.
3. Tag Reform?
Discriminants are logical values associated with enum variants that sometimes have a correspondence to the tags used in-memory representation. Can we provide a method for retrieving a variant's tag only when the discriminant and tag match? Yes, with safe transmute!
#[lang = "enum_trait"]
pub trait Enum {
    //// The discriminant type of the enum.
    type Discriminant;

    /// Produces the discriminant of the given enum variant.
    pub discriminant(&self) -> Self::Discriminant { ... }

    /// Produces the tag of the given enum variant.
    pub fn tag(&self) -> Self::Discriminant
    where
        Self::Discriminant: TransmuteFrom<Self>
    {
        Self::Discriminant::transmute_from(self)
    }
}

That where bound restricts this method to only types where the enum is transmutable into its discriminant; e.g., repr(C) and repr(<primitive>) enums, but not option-like repr(Rust) enums (whose layout is somewhat well-specified), nor any other repr(Rust) enums.

    pub fn tag(&self) -> Self::Discriminant
    where
        Self::Discriminant: TransmuteFrom<Self>
    {
        Self::Discriminant::transmute_from(self)
    }

That doesn't produce the discriminant for Option<NonZeroU8> -- it just produces the u8 value or 0.

That doesn't produce the discriminant tag for Option<NonZeroU8> -- it just produces the u8 value or 0.

Yep, well spotted. It does produce the tag for None, but for Some, the "tag" isn't really a thing that exists. This sort of edge case is why I put a question mark in that heading.
We'd need to reflect a bit more information about layouts into the type system before a Enum::tag method was viable — namely their repr. Something like this:
/// Implemented for all enum `repr`s that have an in-memory tag.
/// Namely: `C`, the primitive reprs (e.g., `u8`), and combinations of `C` and a primitive repr.
pub trait Tagged: Sealed {}

#[lang = "enum_trait"]
pub trait Enum {
    /// The discriminant type of the enum.
    type Discriminant;

    /// A type encoding the `repr` of the enum.
    type Repr;

    /// Produces the discriminant of the given enum variant.
    pub discriminant(&self) -> Self::Discriminant { ... }

    /// Produces the tag of the given enum variant.
    pub fn tag(&self) -> Self::Discriminant
    where
        Self::Repr: Tagged,
        Self::Discriminant: TransmuteFrom<Self>
    {
        Self::Discriminant::transmute_from(self)
    }
}

(Not pictured: a ton of design work and bikeshedding that would need to happen! But, let's not fill up this RFC's issue with comments on this tangent.)
Anyways, there's definitely a path all the way to tag retrieval with this gradual approach. But, even just doing the first two steps would comprehensively address the perils of as.

Thanks @jswrenn for your thoughts here! I was not aware of the fn-pointer footgun, that's special.
On fn-pointers
I think that the bug here is allowing Bar() to be considered a primitive enum variant at all, rather than the fact that it happens to cast to a function pointer.
Ignoring stability concerns, I would suggest that the following simply be compile errors:
#[repr(u8)]
enum Number {
    Zero(),
}

and
enum Number {
    Zero(),
}

fn main() {
    println!("{}", Number::Zero as isize);
}

in the same way that Option cannot be given a primitive repr, and cannot be cast to a primitive. That said, we are where we are.
Possibly more controversially, I would also argue that empty tuple-like or struct-like enum variants should just be outright forbidden, or at least their presence should force an enum to no longer be considered as primitive types.
In practice, for this proposal, I think the refinement needed is to state that the derive-trait will only be supported where none of the variants have tuple-like or struct-like syntax (at least for the first cut). Manually implementing the trait should still be fine, though, and we could potentially expand support in the future. Equivalently, if we end up with an auto Enum trait, my suggestion would be that it not have a numeric Discriminant associated type (perhaps type Discriminant=!;).
On an automatically implemented intrinsic vs an explicitly implemented trait
One of the goals of this RFC is to make stability guarantees more clear, so I'm not sure about automatically implementing a trait vs needing to explicitly implement one (possibly via a derive).
as conversions currently force things like variant ordering to be part of the public API, whether or not that was the author's intent, and I suspect (without data) that this leads to accidental semver-breaking changes in the wild. These probably aren't a significant problem, but it feels in-keeping with the rest of the language that this API should be an opted-in offer of stability, rather than something implemented by default.
There's already std::mem::dicriminant for comparing enum discriminants without leaking the underlying discriminant values.
Is there a strong argument for automatically implementing a trait, rather than requiring opt-in?
On naming
I don't have strong views on having an enum-specific Enum/Discriminant vs a more general IntoUnderlying/Underlying.
On tags
I'd ideally like to avoid tags in this RFC - they feel like a more general form of metadata, rather than specifically concerned with conversion. If we end up with a sealed enum-specific trait we can naturally extend it in the future if we want, otherwise I suggest this should live elsewhere (either a separate trait, or alongside std::mem::discriminant).

Thanks @jswrenn for your thoughts here! I was not aware of the fn-pointer footgun, that's special.
On fn-pointers
I think that the bug here is allowing Bar() to be considered a primitive enum variant at all, rather than the fact that it happens to cast to a function pointer.
Ignoring stability concerns, I would suggest that the following simply be compile errors:
#[repr(u8)]
enum Number {
    Zero(),
}

and
enum Number {
    Zero(),
}

fn main() {
    println!("{}", Number::Zero as isize);
}

in the same way that Option cannot be given a primitive repr, and cannot be cast to a primitive. That said, we are where we are.
Possibly more controversially, I would also argue that empty tuple-like or struct-like enum variants should just be outright forbidden, or at least their presence should force an enum to no longer be considered as primitive types.
In practice, for this proposal, I think the refinement needed is to state that the derive-trait will only be supported where none of the variants have tuple-like or struct-like syntax (at least for the first cut). Manually implementing the trait should still be fine, though, and we could potentially expand support in the future. Equivalently, if we end up with an auto Enum trait, my suggestion would be that it not have a numeric Discriminant associated type (perhaps type Discriminant=!;).
On an automatically implemented intrinsic vs an explicitly implemented trait
One of the goals of this RFC is to make stability guarantees more clear, so I'm not sure about automatically implementing a trait vs needing to explicitly implement one (possibly via a derive).
as conversions currently force things like variant ordering to be part of the public API, whether or not that was the author's intent, and I suspect (without data) that this leads to accidental semver-breaking changes in the wild. These probably aren't a significant problem, but it feels in-keeping with the rest of the language that this API should be an opted-in offer of stability, rather than something implemented by default.
There's already std::mem::dicriminant for comparing enum discriminants without leaking the underlying discriminant values.
Is there a strong argument for automatically implementing a trait, rather than requiring opt-in?
On naming
I don't have strong views on having an enum-specific Enum/Discriminant vs a more general IntoUnderlying/Underlying.
On tags
I'd ideally like to avoid tags in this RFC - they feel like a more general form of metadata, rather than specifically concerned with conversion. If we end up with a sealed enum-specific trait we can naturally extend it in the future if we want, otherwise I suggest this should live elsewhere (either a separate trait, or alongside std::mem::discriminant).

Thanks @jswrenn for your thoughts here! I was not aware of the fn-pointer footgun, that's special.
On fn-pointers
I think that the bug here is allowing Bar() to be considered a primitive enum variant at all, rather than the fact that it happens to cast to a function pointer.
Ignoring stability concerns, I would suggest that the following simply be compile errors:
#[repr(u8)]
enum Number {
    Zero(),
}

and
enum Number {
    Zero(),
}

fn main() {
    println!("{}", Number::Zero as isize);
}

in the same way that Option cannot be given a primitive repr, and cannot be cast to a primitive. That said, we are where we are.
Possibly more controversially, I would also argue that empty tuple-like or struct-like enum variants should just be outright forbidden, or at least their presence should force an enum to no longer be considered as primitive types.
In practice, for this proposal, I think the refinement needed is to state that the derive-trait will only be supported where none of the variants have tuple-like or struct-like syntax (at least for the first cut). Manually implementing the trait should still be fine, though, and we could potentially expand support in the future. Equivalently, if we end up with an auto Enum trait, my suggestion would be that it not have a numeric Discriminant associated type (perhaps type Discriminant=!;).
On an automatically implemented intrinsic vs an explicitly implemented trait
One of the goals of this RFC is to make stability guarantees more clear, so I'm not sure about automatically implementing a trait vs needing to explicitly implement one (possibly via a derive).
as conversions currently force things like variant ordering to be part of the public API, whether or not that was the author's intent, and I suspect (without data) that this leads to accidental semver-breaking changes in the wild. These probably aren't a significant problem, but it feels in-keeping with the rest of the language that this API should be an opted-in offer of stability, rather than something implemented by default.
There's already std::mem::dicriminant for comparing enum discriminants without leaking the underlying discriminant values.
Is there a strong argument for automatically implementing a trait, rather than requiring opt-in?
On naming
I don't have strong views on having an enum-specific Enum/Discriminant vs a more general IntoUnderlying/Underlying.
On tags
I'd ideally like to avoid tags in this RFC - they feel like a more general form of metadata, rather than specifically concerned with conversion. If we end up with a sealed enum-specific trait we can naturally extend it in the future if we want, otherwise I suggest this should live elsewhere (either a separate trait, or alongside std::mem::discriminant).

Thanks @jswrenn for your thoughts here! I was not aware of the fn-pointer footgun, that's special.
On fn-pointers
I think that the bug here is allowing Bar() to be considered a primitive enum variant at all, rather than the fact that it happens to cast to a function pointer.
Ignoring stability concerns, I would suggest that the following simply be compile errors:
#[repr(u8)]
enum Number {
    Zero(),
}

and
enum Number {
    Zero(),
}

fn main() {
    println!("{}", Number::Zero as isize);
}

in the same way that Option cannot be given a primitive repr, and cannot be cast to a primitive. That said, we are where we are.
Possibly more controversially, I would also argue that empty tuple-like or struct-like enum variants should just be outright forbidden, or at least their presence should force an enum to no longer be considered as primitive types.
In practice, for this proposal, I think the refinement needed is to state that the derive-trait will only be supported where none of the variants have tuple-like or struct-like syntax (at least for the first cut). Manually implementing the trait should still be fine, though, and we could potentially expand support in the future. Equivalently, if we end up with an auto Enum trait, my suggestion would be that it not have a numeric Discriminant associated type (perhaps type Discriminant=!;).
On an automatically implemented intrinsic vs an explicitly implemented trait
One of the goals of this RFC is to make stability guarantees more clear, so I'm not sure about automatically implementing a trait vs needing to explicitly implement one (possibly via a derive).
as conversions currently force things like variant ordering to be part of the public API, whether or not that was the author's intent, and I suspect (without data) that this leads to accidental semver-breaking changes in the wild. These probably aren't a significant problem, but it feels in-keeping with the rest of the language that this API should be an opted-in offer of stability, rather than something implemented by default.
There's already std::mem::dicriminant for comparing enum discriminants without leaking the underlying discriminant values.
Is there a strong argument for automatically implementing a trait, rather than requiring opt-in?
On naming
I don't have strong views on having an enum-specific Enum/Discriminant vs a more general IntoUnderlying/Underlying.
On tags
I'd ideally like to avoid tags in this RFC - they feel like a more general form of metadata, rather than specifically concerned with conversion. If we end up with a sealed enum-specific trait we can naturally extend it in the future if we want, otherwise I suggest this should live elsewhere (either a separate trait, or alongside std::mem::discriminant).

Is there a strong argument for automatically implementing a trait, rather than requiring opt-in?

Yes: all enums already have an associated discriminant type, and knowing that type is important to as casting variants of the enum without shooting yourself in the foot. Both the discriminant type and the ability (or lack thereof) to as cast variants of an enum is dictated solely by the definition of the enum — not by the implementation of traits. Rust will currently tell you whether you can as cast a variant, but it won't tell you the correct discriminant type; you need to look at the definition yourself to find it. An intrinsic mem::Enum trait with an associated Discriminant type closes this gap.
Such a trait would be to make as casting less of a foot-gun, but not to make stability guarantees clearer. Combined with a lint, it'd be a small-yet-broadly-applicable improvement to the clarity of enum as casting in existing codebases.
This trait should be placed in mem (not convert), as it reflects the memory layout properties of a type, and not its stability properties (like most everything else in mem).

If such a trait makes stability guarantees clearer, it's only insofar that it might draw more attention to the incredibly subtle stability implications of enum discriminants that already exist. If we could roll back the clock to pre-1.0, I'd say there isn't a compelling argument for discriminants and as-casting on #[repr(Rust)] enums. They are terribly implicit, whereas Rust favors the explicit.  In virtually every use-case for as-casting on #[repr(Rust)] enums, an explicit From implementation would be a better choice.
In contrast, discriminants on #[repr(C)] and #[repr(<primitive>)] enums have a real purpose: they control the memory layout of variants. Here, a long-term approach to enum reform could include discouraging as casting and, once arbitrary_enum_discriminant is stabilized, discourage relying on implicitly-set discriminants.
Broadly: I see comprehensive enum reform as a long-term social challenge. Given that we can't merely turn back the clock, the best we can do is to nudge people in the right direction with lints over a suitably long period of time and then perhaps an edition change. Skipping right to introducing a new core::convert::IntoUnderlying trait could give the misleading impression that enum discriminants in the absence of an IntoUnderlying implementation aren't part of an enum's stability guarantee — but they are! We should tread carefully.

Is there a strong argument for automatically implementing a trait, rather than requiring opt-in?

Yes: all enums already have an associated discriminant type, and knowing that type is important to as casting variants of the enum without shooting yourself in the foot. Both the discriminant type and the ability (or lack thereof) to as cast variants of an enum is dictated solely by the definition of the enum — not by the implementation of traits. Rust will currently tell you whether you can as cast a variant, but it won't tell you the correct discriminant type; you need to look at the definition yourself to find it. An intrinsic mem::Enum trait with an associated Discriminant type closes this gap.
Such a trait would be to make as casting less of a foot-gun, but not to make stability guarantees clearer. Combined with a lint, it'd be a small-yet-broadly-applicable improvement to the clarity of enum as casting in existing codebases.
This trait should be placed in mem (not convert), as it reflects the memory layout properties of a type, and not its stability properties (like most everything else in mem).

If such a trait makes stability guarantees clearer, it's only insofar that it might draw more attention to the incredibly subtle stability implications of enum discriminants that already exist. If we could roll back the clock to pre-1.0, I'd say there isn't a compelling argument for discriminants and as-casting on #[repr(Rust)] enums. They are terribly implicit, whereas Rust favors the explicit.  In virtually every use-case for as-casting on #[repr(Rust)] enums, an explicit From implementation would be a better choice.
In contrast, discriminants on #[repr(C)] and #[repr(<primitive>)] enums have a real purpose: they control the memory layout of variants. Here, a long-term approach to enum reform could include discouraging as casting and, once arbitrary_enum_discriminant is stabilized, discourage relying on implicitly-set discriminants.
Broadly: I see comprehensive enum reform as a long-term social challenge. Given that we can't merely turn back the clock, the best we can do is to nudge people in the right direction with lints over a suitably long period of time and then perhaps an edition change. Skipping right to introducing a new core::convert::IntoUnderlying trait could give the misleading impression that enum discriminants in the absence of an IntoUnderlying implementation aren't part of an enum's stability guarantee — but they are! We should tread carefully.

tl;dr: If we're trying to make as-casts more safe, I think a blanket Enum implementation is a great incremental step. But it's a local optimum and a compromise. If we think we can get to a point where as-casts could be deprecated or even removed, we should avoid automatically exposing the discriminant, because it's a step in the opposite direction, and would be hard to undo.
I think that all generally makes sense, but there's a question as to whether in the long term we want discriminants to always be part of an enum's stability guarantee.
There are enums where their representation is an incidental detail, and not intended to be stable; imagine:
enum Color {
    Red,
    Green,
    Blue,
    ...
}

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.
I'm hoping we have a choice as to the road forwards; we can either accept that all enums must include their representation in their stability guarantee, or we can work towards enabling hiding representation from stability guarantees. Maybe because we shipped as-casts in 1.0, we don't have a choice here, and all enums must always have a stable representation, but I'm hoping after perhaps a very long path we can enable that optionality. But introducing an unconditional way of retrieving that repr makes that much harder to do.
I guess an alternative road forwards could be to introduce something like #[repr(opaque)] to explicitly opt out of stability guarantees, but if we can, the language tends to favour guarantees being things that are opted in to, rather than opted out of.

tl;dr: If we're trying to make as-casts more safe, I think a blanket Enum implementation is a great incremental step. But it's a local optimum and a compromise. If we think we can get to a point where as-casts could be deprecated or even removed, we should avoid automatically exposing the discriminant, because it's a step in the opposite direction, and would be hard to undo.
I think that all generally makes sense, but there's a question as to whether in the long term we want discriminants to always be part of an enum's stability guarantee.
There are enums where their representation is an incidental detail, and not intended to be stable; imagine:
enum Color {
    Red,
    Green,
    Blue,
    ...
}

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.
I'm hoping we have a choice as to the road forwards; we can either accept that all enums must include their representation in their stability guarantee, or we can work towards enabling hiding representation from stability guarantees. Maybe because we shipped as-casts in 1.0, we don't have a choice here, and all enums must always have a stable representation, but I'm hoping after perhaps a very long path we can enable that optionality. But introducing an unconditional way of retrieving that repr makes that much harder to do.
I guess an alternative road forwards could be to introduce something like #[repr(opaque)] to explicitly opt out of stability guarantees, but if we can, the language tends to favour guarantees being things that are opted in to, rather than opted out of.

If we think we can get to a point where as-casts could be deprecated or even removed, we should avoid automatically exposing the discriminant, because it's a step in the opposite direction, and would be hard to undo.

Not so hard: we'd just deprecate the trait! :) But, the trait would continue to be very useful in the case of #[repr(C/primitive)] enums, since having available for that would reduce some memory-safety hazards in the sort of code those enums tend to be used with (b.c. tag manipulations often involve unsafe code). And, again, nothing in mem carries semver stability guarantees so I don't see this posing much of a novel hazard. It's just like how the existence of size_of doesn't mean type size is part of stability guarantees; rather, it makes programmer assumptions about type size trivial to check.

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

I totally agree with this ideal. Unfortunately, many stability hazards (and more!) stem from the existence as casting. They're stupidly subtle. For instance, it can be a breaking change to add variants to this enum:
#[non_exhaustive]
enum Foo {
    Bar
}

...because if we add the variant Baz(u8), suddenly all prior Foo::Bar as isize casts become compile errors.
And the stability hazards unrelated to as are even worse. For instance, it can be a breaking change to add variants to this enum:
#[non_exhaustive]
enum Foo<T> {
    Bar(T)
}

...because if we add the variant Baz, then this will be a compile error:
#[repr(transparent)]
struct Bar(u8, Foo<!>);

(Oh no, that's not currently producing a compile error if I make that change...)
A design of a more opaque enum would need to thoroughly account for these stability hazards, and more. (@joshlf's 2020 call for "private enum variants" comes to mind.) Otherwise we'd just end up with a new kind of enum that merely has its own distinct set of subtleties to worry about.

If we think we can get to a point where as-casts could be deprecated or even removed, we should avoid automatically exposing the discriminant, because it's a step in the opposite direction, and would be hard to undo.

Not so hard: we'd just deprecate the trait! :) But, the trait would continue to be very useful in the case of #[repr(C/primitive)] enums, since having available for that would reduce some memory-safety hazards in the sort of code those enums tend to be used with (b.c. tag manipulations often involve unsafe code). And, again, nothing in mem carries semver stability guarantees so I don't see this posing much of a novel hazard. It's just like how the existence of size_of doesn't mean type size is part of stability guarantees; rather, it makes programmer assumptions about type size trivial to check.

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

I totally agree with this ideal. Unfortunately, many stability hazards (and more!) stem from the existence as casting. They're stupidly subtle. For instance, it can be a breaking change to add variants to this enum:
#[non_exhaustive]
enum Foo {
    Bar
}

...because if we add the variant Baz(u8), suddenly all prior Foo::Bar as isize casts become compile errors.
And the stability hazards unrelated to as are even worse. For instance, it can be a breaking change to add variants to this enum:
#[non_exhaustive]
enum Foo<T> {
    Bar(T)
}

...because if we add the variant Baz, then this will be a compile error:
#[repr(transparent)]
struct Bar(u8, Foo<!>);

(Oh no, that's not currently producing a compile error if I make that change...)
A design of a more opaque enum would need to thoroughly account for these stability hazards, and more. (@joshlf's 2020 call for "private enum variants" comes to mind.) Otherwise we'd just end up with a new kind of enum that merely has its own distinct set of subtleties to worry about.

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

Additionally: As written, I'm not sure that this RFC moves towards this goal. Take, for instance, this example in the RFC:
#[derive(IntoUnderlying)]
#[repr(u8)]
enum Number {
    Zero,
    One,
}

fn main() {
    assert_eq!(Number::Zero.into_underlying(), 0_u8);
}

This still exposes the ordering issues of implicit discriminants and as casting! If we reorder the variants, or insert a variant before One or Zero, the assertion will fail.
Here, as with as casts, the devil is in implicitly set discriminants. If the author had instead written:
#[repr(u8)]
enum Number {
    Zero = 0,
    One = 1,
}

...there's no danger in reordering those variants, or adding new unit variants.
So, what would improve this situation is linting against implicitly set discriminants.

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

Additionally: As written, I'm not sure that this RFC moves towards this goal. Take, for instance, this example in the RFC:
#[derive(IntoUnderlying)]
#[repr(u8)]
enum Number {
    Zero,
    One,
}

fn main() {
    assert_eq!(Number::Zero.into_underlying(), 0_u8);
}

This still exposes the ordering issues of implicit discriminants and as casting! If we reorder the variants, or insert a variant before One or Zero, the assertion will fail.
Here, as with as casts, the devil is in implicitly set discriminants. If the author had instead written:
#[repr(u8)]
enum Number {
    Zero = 0,
    One = 1,
}

...there's no danger in reordering those variants, or adding new unit variants.
So, what would improve this situation is linting against implicitly set discriminants.

Having a Enum::try_from(int) would be useful.
For example, in a pratt parser, to get the next level of precedence, I am at the moment using mem::transmute(precedence as u8 + 1) to get the next variant of the enum (with a dummy variant at the end).

Having a Enum::try_from(int) would be useful.
For example, in a pratt parser, to get the next level of precedence, I am at the moment using mem::transmute(precedence as u8 + 1) to get the next variant of the enum (with a dummy variant at the end).

If we think we can get to a point where as-casts could be deprecated or even removed, we should avoid automatically exposing the discriminant, because it's a step in the opposite direction, and would be hard to undo.

Not so hard: we'd just deprecate the trait! :)

But we don't like doing this in std!

But, the trait would continue to be very useful in the case of #[repr(C/primitive)] enums, since having such a trait would reduce some memory-safety hazards in the sort of code those enums tend to be used with (b.c. tag manipulations often involve unsafe code).

How would you feel about automatically deriving this trait only for explicitly repr'd enums, with no fields? i.e. no Enum impl for:
enum Color {
    Red,
    Blue,
}

or
#[repr(u8)]
enum Color {
    RGB(u8, u8, u8),
}

But one for:
#[repr(u8)]
enum Color {
    Red,
    Blue,
}

The idea being that by being explicit about the layout of your enum, you're opting in to exposing that information (and as you note, in a non-stability-opting-in way). I suspect (again, without data) that most enums which aren't intended to be interchangeable with numbers or passed over FFI boundaries don't have an explicit repr, though I'm not sure how confident I would be in claiming that most enums which do have an explicit repr are intended for these purposes.
That's the reason I'm looking for an explicit attribute, and I think an explicit repr is a sufficient explicit attribute.

And, again, nothing in mem carries semver stability guarantees so I don't see this posing much of a novel hazard. It's just like how the existence of size_of doesn't mean type size is part of stability guarantees; rather, it makes programmer assumptions about type size trivial to check programmatically.

👍

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

I totally agree with this ideal. Unfortunately, many stability hazards (and more!) stem from the existence as casting. They're stupidly subtle. For instance, it can be a breaking change to add variants to this enum:
#[non_exhaustive]
enum Foo {
    Bar
}

...because if we add the variant Baz(u8), suddenly all prior Foo::Bar as isize casts become compile errors.

The thing I find upsetting about this is that this is valid:
#[repr(u8)]
pub enum Foo {
  Bar,
  Baz(u16),
}

which arguably it shouldn't be - what does this repr attribute even mean? But I think if we're happy with "explicit repr, no fields or constructor means you get an Enum definition", we can make this hazard go away easily.

And the stability hazards unrelated to as are even worse. For instance, in:
#[non_exhaustive]
pub enum Foo {
  Bar,
  // Baz,
}

#[repr(transparent)]
struct Fizz(u8, Foo);

...uncommenting the Baz variant causes this snippet to produce a compile error at the definition of Fizz.
A design of a more opaque enum would need to thoroughly account for these stability hazards, and more. (@joshlf's 2020 call for "private enum variants" comes to mind.) Otherwise, we might just end up with a new kind of enum that merely has its own distinct set of subtleties to worry about.

I did not realise this one! Again, though, requiring an explicit repr attribute makes this problem go away, as:
#[non_exhaustive]
#[repr(u8)]
pub enum Foo {
  Bar,
}

is not zero-sized.

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

Additionally: As written, I'm not sure that this RFC moves towards this goal. Take, for instance, this example in the RFC:
#[derive(IntoUnderlying)]
#[repr(u8)]
enum Number {
    Zero,
    One,
}

fn main() {
    assert_eq!(Number::Zero.into_underlying(), 0_u8);
}

This still exposes the ordering issues of implicit discriminants and as casting! If we reorder the variants, or insert a variant before One or Zero, the assertion will fail.
Here, as with as casts, the devil is in implicitly set discriminants. If the author had instead written:
#[repr(u8)]
enum Number {
    Zero = 0,
    One = 1,
}

...there would be no danger in reordering those variants, or adding new unit variants.
So, what would improve this situation is linting against implicitly set discriminants.

I think that the explicitness of the attributes make this ok; either (and definitely both) of setting #[derive(IntoUnderlying)] and #[repr(u8)] is the author stating "The values of these enum variants are intentional", whether they're explicitly or implicitly stated. It's really the explicitness of "I've thought about these values" that I'm looking to have people opt in to, and I don't really mind how that opt-in happens.

If we think we can get to a point where as-casts could be deprecated or even removed, we should avoid automatically exposing the discriminant, because it's a step in the opposite direction, and would be hard to undo.

Not so hard: we'd just deprecate the trait! :)

But we don't like doing this in std!

But, the trait would continue to be very useful in the case of #[repr(C/primitive)] enums, since having such a trait would reduce some memory-safety hazards in the sort of code those enums tend to be used with (b.c. tag manipulations often involve unsafe code).

How would you feel about automatically deriving this trait only for explicitly repr'd enums, with no fields? i.e. no Enum impl for:
enum Color {
    Red,
    Blue,
}

or
#[repr(u8)]
enum Color {
    RGB(u8, u8, u8),
}

But one for:
#[repr(u8)]
enum Color {
    Red,
    Blue,
}

The idea being that by being explicit about the layout of your enum, you're opting in to exposing that information (and as you note, in a non-stability-opting-in way). I suspect (again, without data) that most enums which aren't intended to be interchangeable with numbers or passed over FFI boundaries don't have an explicit repr, though I'm not sure how confident I would be in claiming that most enums which do have an explicit repr are intended for these purposes.
That's the reason I'm looking for an explicit attribute, and I think an explicit repr is a sufficient explicit attribute.

And, again, nothing in mem carries semver stability guarantees so I don't see this posing much of a novel hazard. It's just like how the existence of size_of doesn't mean type size is part of stability guarantees; rather, it makes programmer assumptions about type size trivial to check programmatically.

👍

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

I totally agree with this ideal. Unfortunately, many stability hazards (and more!) stem from the existence as casting. They're stupidly subtle. For instance, it can be a breaking change to add variants to this enum:
#[non_exhaustive]
enum Foo {
    Bar
}

...because if we add the variant Baz(u8), suddenly all prior Foo::Bar as isize casts become compile errors.

The thing I find upsetting about this is that this is valid:
#[repr(u8)]
pub enum Foo {
  Bar,
  Baz(u16),
}

which arguably it shouldn't be - what does this repr attribute even mean? But I think if we're happy with "explicit repr, no fields or constructor means you get an Enum definition", we can make this hazard go away easily.

And the stability hazards unrelated to as are even worse. For instance, in:
#[non_exhaustive]
pub enum Foo {
  Bar,
  // Baz,
}

#[repr(transparent)]
struct Fizz(u8, Foo);

...uncommenting the Baz variant causes this snippet to produce a compile error at the definition of Fizz.
A design of a more opaque enum would need to thoroughly account for these stability hazards, and more. (@joshlf's 2020 call for "private enum variants" comes to mind.) Otherwise, we might just end up with a new kind of enum that merely has its own distinct set of subtleties to worry about.

I did not realise this one! Again, though, requiring an explicit repr attribute makes this problem go away, as:
#[non_exhaustive]
#[repr(u8)]
pub enum Foo {
  Bar,
}

is not zero-sized.

The enum author may want the freedom to grow the enum arbitrarily, restrict it to a smaller size, or re-order variants as they wish in the future.

Additionally: As written, I'm not sure that this RFC moves towards this goal. Take, for instance, this example in the RFC:
#[derive(IntoUnderlying)]
#[repr(u8)]
enum Number {
    Zero,
    One,
}

fn main() {
    assert_eq!(Number::Zero.into_underlying(), 0_u8);
}

This still exposes the ordering issues of implicit discriminants and as casting! If we reorder the variants, or insert a variant before One or Zero, the assertion will fail.
Here, as with as casts, the devil is in implicitly set discriminants. If the author had instead written:
#[repr(u8)]
enum Number {
    Zero = 0,
    One = 1,
}

...there would be no danger in reordering those variants, or adding new unit variants.
So, what would improve this situation is linting against implicitly set discriminants.

I think that the explicitness of the attributes make this ok; either (and definitely both) of setting #[derive(IntoUnderlying)] and #[repr(u8)] is the author stating "The values of these enum variants are intentional", whether they're explicitly or implicitly stated. It's really the explicitness of "I've thought about these values" that I'm looking to have people opt in to, and I don't really mind how that opt-in happens.

Having a Enum::try_from(int) would be useful.
For example, in a pratt parser, to get the next level of precedence, I am at the moment using mem::transmute(precedence as u8 + 1) to get the next variant of the enum (with a dummy variant at the end).

I completely agree! In the mean time, might I suggest the num_enum crate, which allows you to derive a TryFrom implementation :)

Having a Enum::try_from(int) would be useful.
For example, in a pratt parser, to get the next level of precedence, I am at the moment using mem::transmute(precedence as u8 + 1) to get the next variant of the enum (with a dummy variant at the end).

I completely agree! In the mean time, might I suggest the num_enum crate, which allows you to derive a TryFrom implementation :)

It's really the explicitness of "I've thought about these values" that I'm looking to have people opt in to, and I don't really mind how that opt-in happens.

If you want to signal that your enum should be SemVer-stably convertible to or from a primitive value, you (probably) should do so with the same mechanism you'd use for any other type: by implementing From, Into and Try{From,Into}. To make this transition extra ergonomic:

permit #[derive(Into)] on C-like enums with explicit discriminants
permit #[derive(TryFrom)] on data-free enums with explicit discriminants

Why the C-like and data-free restrictions?

A C-like enum is one in which every variant is a unit variant (i.e. not ending with {} or ()). Currently, it is only for C-like enums that every variant is as-castable into its discriminant.
A data-free enum is one in which every variant is fieldless. It is only for these enums that every variant can be wholly created from just its discriminant (in the logical sense; not necessarily in the in-memory layout sense).

Why require explicit discriminants?

If you were to write these implementations out by hand, you would need be explicit about the correspondence between variants and values. Requiring the same degree of explicitness for these derives demonstrates that you've thought about the particulars of the conversion.

Why not require an explicit repr?

Whether or not you use an explicit repr is mostly orthogonal to the issue of conversion. The primary purpose of an explicit repr is to manipulate the in-memory layout of an enum. There is very good reason to leave out the repr if you don't care about in-memory layout. The discriminant type of enum Foo { Bar = 0isize, Baz = 1isize } is isize, but Foo is represented with only one byte! That's not the case if you annotate Foo with repr(isize).

My primary concern about stability reform is that I'm sure that there have been Rust programmers who assumed that discriminants are SemVer stable because they're observable with as casting. In the absence of clear, official guidance, that's a totally reasonable position to take. But this sort of enum stability reform would effectively be breaking change for these folks. I'm not saying it's impossible, but it's more of a social challenge than a technical one.

It's really the explicitness of "I've thought about these values" that I'm looking to have people opt in to, and I don't really mind how that opt-in happens.

If you want to signal that your enum should be SemVer-stably convertible to or from a primitive value, you (probably) should do so with the same mechanism you'd use for any other type: by implementing From, Into and Try{From,Into}. To make this transition extra ergonomic:

permit #[derive(Into)] on C-like enums with explicit discriminants
permit #[derive(TryFrom)] on data-free enums with explicit discriminants

Why the C-like and data-free restrictions?

A C-like enum is one in which every variant is a unit variant (i.e. not ending with {} or ()). Currently, it is only for C-like enums that every variant is as-castable into its discriminant.
A data-free enum is one in which every variant is fieldless. It is only for these enums that every variant can be wholly created from just its discriminant (in the logical sense; not necessarily in the in-memory layout sense).

Why require explicit discriminants?

If you were to write these implementations out by hand, you would need be explicit about the correspondence between variants and values. Requiring the same degree of explicitness for these derives demonstrates that you've thought about the particulars of the conversion.

Why not require an explicit repr?

Whether or not you use an explicit repr is mostly orthogonal to the issue of conversion. The primary purpose of an explicit repr is to manipulate the in-memory layout of an enum. There is very good reason to leave out the repr if you don't care about in-memory layout. The discriminant type of enum Foo { Bar = 0isize, Baz = 1isize } is isize, but Foo is represented with only one byte! That's not the case if you annotate Foo with repr(isize).

My primary concern about stability reform is that I'm sure that there have been Rust programmers who assumed that discriminants are SemVer stable because they're observable with as casting. In the absence of clear, official guidance, that's a totally reasonable position to take. But this sort of enum stability reform would effectively be breaking change for these folks. I'm not saying it's impossible, but it's more of a social challenge than a technical one.

It's really the explicitness of "I've thought about these values" that I'm looking to have people opt in to, and I don't really mind how that opt-in happens.

If you want to signal that your enum should be SemVer-stably convertible to or from a primitive value, you (probably) should do so with the same mechanism you'd use for any other type: by implementing From, Into and Try{From,Into}. To make this transition extra ergonomic:

permit #[derive(Into)] on C-like enums with explicit discriminants
permit #[derive(TryFrom)] on data-free enums with explicit discriminants

If you take a look at https://github.com/rust-lang/rfcs/pull/3040, that was actually how this proposal started (specifically #[derive(Into)]), but we changed direction because:

#[derive(Into)] is not 100% clear what target type Into is being derived for.
Into in general makes no claims about the cost of the conversion, and some users of as value that attestation of cheapness.

Maybe, though, the real answer is that we want both for different purposes; an Enum sealed auto-implemented trait which gives access to the discriminant type (and potentially other things), and the ability to derive stable conversion, and the two needn't be linked.

My primary concern about stability reform is that I'm sure that there have been Rust programmers who assumed that discriminants are SemVer stable because they're observable with as casting. In the absence of clear, official guidance, that's a totally reasonable position to take. But this sort of enum stability reform would effectively be breaking change for these folks. I'm not saying it's impossible, but it's more of a social challenge than a technical one.

Yes, I completely agree. I think that the aim of https://github.com/rust-lang/rfcs/pull/3040 is to start the conversation about what that official guidance around as conversions should be. Regardless of that, though, I think that several of the steps (making it easier to perform the conversion with a trait, be that Into or IntoUnderlying), and linting for potentially truncating conversions, are stand-alone useful steps.
Thanks @jswrenn, by the way, for all of the time, thought, and effort you're putting in to helping to shape this direction (and all of the terrifying edge-cases you've been pointing out on the way), I really appreciate your thoughtful and knowledgable help!

It's really the explicitness of "I've thought about these values" that I'm looking to have people opt in to, and I don't really mind how that opt-in happens.

If you want to signal that your enum should be SemVer-stably convertible to or from a primitive value, you (probably) should do so with the same mechanism you'd use for any other type: by implementing From, Into and Try{From,Into}. To make this transition extra ergonomic:

permit #[derive(Into)] on C-like enums with explicit discriminants
permit #[derive(TryFrom)] on data-free enums with explicit discriminants

If you take a look at https://github.com/rust-lang/rfcs/pull/3040, that was actually how this proposal started (specifically #[derive(Into)]), but we changed direction because:

#[derive(Into)] is not 100% clear what target type Into is being derived for.
Into in general makes no claims about the cost of the conversion, and some users of as value that attestation of cheapness.

Maybe, though, the real answer is that we want both for different purposes; an Enum sealed auto-implemented trait which gives access to the discriminant type (and potentially other things), and the ability to derive stable conversion, and the two needn't be linked.

My primary concern about stability reform is that I'm sure that there have been Rust programmers who assumed that discriminants are SemVer stable because they're observable with as casting. In the absence of clear, official guidance, that's a totally reasonable position to take. But this sort of enum stability reform would effectively be breaking change for these folks. I'm not saying it's impossible, but it's more of a social challenge than a technical one.

Yes, I completely agree. I think that the aim of https://github.com/rust-lang/rfcs/pull/3040 is to start the conversation about what that official guidance around as conversions should be. Regardless of that, though, I think that several of the steps (making it easier to perform the conversion with a trait, be that Into or IntoUnderlying), and linting for potentially truncating conversions, are stand-alone useful steps.
Thanks @jswrenn, by the way, for all of the time, thought, and effort you're putting in to helping to shape this direction (and all of the terrifying edge-cases you've been pointing out on the way), I really appreciate your thoughtful and knowledgable help!

1. #[derive(Into)] is not 100% clear what target type Into is being derived for.

If you require explicit discriminants for #[derive(Into)], it is pretty clear what the type and particulars of the conversion is: it's whatever the discriminants are.
I won't say it's 100% clear, but it's pretty close — the case that enum discriminants have a default type of isize still remains, but we're stuck with that. If we really want to make this case more explicit, we could implement a lint that warns on unsuffixed discriminant values on default repr enums. (And this could be done independently from any new traits.)
Non-trivial dervies always involve a sacrifice of explicitness. For instance, it's not explicitly clear how derive(Hash) computes hashes, nor how derive(PartialOrd) defines orderings — but that's just part of using a shorthand.

2. Into in general makes no claims about the cost of the conversion, and some users of as value that attestation of cheapness.

Those users would be mistaken to do so; as carries no formal promise of cheapness! And what constitutes "cheap" depends on the situation. It is potentially infinitely cheaper to work with values of enum Foo { Bar } than it is to work with Foo::Bar as isize. And while some as conversions are cheap truncations, others involve relatively expensive manipulations (like conversions to/from floating point numbers).
The issue of "cheapness" aside, there's already a version of Into that does carry some connotation of cheapness: AsRef.
Concretely, this:
#[derive(AsRef)]
enum Foo {
    A = 1,
    B = 2,
    C = 3,
}

...could expand to this:
impl AsRef<isize> for Foo {
    fn as_ref(&self) -> &'static isize {
        match self {
            Foo::A => &1,
            Foo::B => &2,
            Foo::C => &3,
        }
    }
}

So, let me amend my proposal:

permit #[derive(Into)] and #[derive(AsRef)] on C-like enums with explicit discriminants
permit #[derive(TryFrom)] on data-free enums with explicit discriminants

Maybe, though, the real answer is that we want both for different purposes; an Enum sealed auto-implemented trait which gives access to the discriminant type (and potentially other things), and the ability to derive stable conversion, and the two needn't be linked.

Yep, this is my thinking, too — these issues can be (and should be) treated basically independently from each other.

1. #[derive(Into)] is not 100% clear what target type Into is being derived for.

If you require explicit discriminants for #[derive(Into)], it is pretty clear what the type and particulars of the conversion is: it's whatever the discriminants are.
I won't say it's 100% clear, but it's pretty close — the case that enum discriminants have a default type of isize still remains, but we're stuck with that. If we really want to make this case more explicit, we could implement a lint that warns on unsuffixed discriminant values on default repr enums. (And this could be done independently from any new traits.)
Non-trivial dervies always involve a sacrifice of explicitness. For instance, it's not explicitly clear how derive(Hash) computes hashes, nor how derive(PartialOrd) defines orderings — but that's just part of using a shorthand.

2. Into in general makes no claims about the cost of the conversion, and some users of as value that attestation of cheapness.

Those users would be mistaken to do so; as carries no formal promise of cheapness! And what constitutes "cheap" depends on the situation. It is potentially infinitely cheaper to work with values of enum Foo { Bar } than it is to work with Foo::Bar as isize. And while some as conversions are cheap truncations, others involve relatively expensive manipulations (like conversions to/from floating point numbers).
The issue of "cheapness" aside, there's already a version of Into that does carry some connotation of cheapness: AsRef.
Concretely, this:
#[derive(AsRef)]
enum Foo {
    A = 1,
    B = 2,
    C = 3,
}

...could expand to this:
impl AsRef<isize> for Foo {
    fn as_ref(&self) -> &'static isize {
        match self {
            Foo::A => &1,
            Foo::B => &2,
            Foo::C => &3,
        }
    }
}

So, let me amend my proposal:

permit #[derive(Into)] and #[derive(AsRef)] on C-like enums with explicit discriminants
permit #[derive(TryFrom)] on data-free enums with explicit discriminants

Maybe, though, the real answer is that we want both for different purposes; an Enum sealed auto-implemented trait which gives access to the discriminant type (and potentially other things), and the ability to derive stable conversion, and the two needn't be linked.

Yep, this is my thinking, too — these issues can be (and should be) treated basically independently from each other.

bikeshedding: CastInto might be a better name to imply it's trivial rather than calling it TrivialInto?

bikeshedding: CastInto might be a better name to imply it's trivial rather than calling it TrivialInto?

IntoRaw?

@liigo Looks like it's going in the direction of AsRepr, per the libs conversation in https://github.com/rust-lang/rust/pull/81642#issuecomment-862673931


1.20?

Describe the Suggestion
A version for 1.20?
Screenshots and Videos
No response
Additional Context
No response

I may going out on a limb here but I think it'll be out when it's ready?


Need help for my configuration

Hey @NTBBloodbath how can I disable null_ls from showing in GetLspClient provider ?

Hey, there was a PR for this and just merged it (#31). You can take a look at the PR description for the syntax.
Cheers!


"No such file or directory" for depthxxx.npy when generate private data

When I generate private data by using
python exp_preprocess.py --data_type private
But I got this issue:

When I found code in the file sfm_mvs.py, maybe the problem exits here:

The file depthxxx.npy is not generate, but it needs to load.

I have saved this issue.
Because the generate .npy name is not like depth_fileName.npy.
It's like depth0001.npy.

So I changed sfm_mvs.py file, line 177 as follows:


Sharing from some apps to Vector not working

Verizon Motorola MAXX (Android v 6.0).
Some apps share correctly (Contacts, Gallery, Leafpic, Smugmug), but other apps are not sharing correctly with Vector. They just open up Vector but don't prompt for a room to share with:

Firefox
Spotify
Google+
Slide (Reddit app)
Simpletask
IMDB
Maps
Shazam
Youtube

Thanks!
Scott

Same issue with contacts
https://github.com/vector-im/vector-android/issues/208

Should be fixed with https://github.com/vector-im/vector-android/commit/1c8a380f8529dcb0ab01c0be78626f1d36cb7aec


Converted time in send_response body is a year ahead

Reported in BD-4244 during development https://fioprotocol.atlassian.net/jira/software/c/projects/BD/boards/2?modal=detail&selectedIssue=BD-4244 domain expiration time in the send_response section of the transaction receipts are in 2 years instead of 1

Fix is pending review and qa testing https://github.com/fioprotocol/fio.contracts/pull/278/commits/1664bdddf5c4c5479a948c9bfe615d3b17d75871


Move Line Up, Move Line Down

@kaunteya Hi, You've done great work, I was looking for the Move Line UP and Move Line DOWN features.
If you could add it in your extension, it would be great extensions

Hey. Thanks..
Move line up /down is already there in the Xcode


[Bug] Add a placeholder to the mongo host address field

Summary
Some users add the SRV to the mongo host address not knowing what value is expected there

Backend change has been merged. UI change trakced via: https://github.com/appsmithorg/appsmith/issues/3334

Closed via #3334