Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Never type experiments #84573

Closed

Conversation

Mark-Simulacrum
Copy link
Member

This currently just rebases #79470 (hopefully all correctly), but will "soon" follow up with an implementation as per rust-lang/lang-team#60 (comment).

r? @ghost

@Mark-Simulacrum Mark-Simulacrum self-assigned this Apr 26, 2021
@Mark-Simulacrum Mark-Simulacrum added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 26, 2021
@rust-log-analyzer

This comment has been minimized.

@Mark-Simulacrum
Copy link
Member Author

As an update - I just pushed the new v2 fallback algorithm we had originally discussed; this currently doesn't quite pass tests in-tree but does address some of the known cases the v1 fallback algorithm failed at.

Niko and I spent a bit of time discussing possible solutions to the problems v2 brings up but didn't arrive at anything concrete yet.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented May 14, 2021

☔ The latest upstream changes (presumably #84107) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented May 18, 2021

☔ The latest upstream changes (presumably #84767) made this pull request unmergeable. Please resolve the merge conflicts.

@Mark-Simulacrum Mark-Simulacrum force-pushed the never-type-fallback-new branch 2 times, most recently from 8d23405 to df59117 Compare May 20, 2021 16:54
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented May 22, 2021

☔ The latest upstream changes (presumably #85078) made this pull request unmergeable. Please resolve the merge conflicts.

@Mark-Simulacrum Mark-Simulacrum force-pushed the never-type-fallback-new branch 2 times, most recently from a5d60c5 to 3dc4f18 Compare May 24, 2021 21:03
@rust-log-analyzer

This comment has been minimized.

@Mark-Simulacrum Mark-Simulacrum force-pushed the never-type-fallback-new branch 2 times, most recently from 3e88c1b to 4c74421 Compare May 24, 2021 21:54
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented May 25, 2021

☔ The latest upstream changes (presumably #84985) made this pull request unmergeable. Please resolve the merge conflicts.

nikomatsakis and others added 8 commits August 30, 2021 17:55
Instead, we now rely on the code that looks for a NeverToAny adjustment.
This could cause us to visit the start node twice.
Extend the `DepthFirstSearch` iterator so that it can be re-used and
extended with add'l start nodes. Then replace the FxHashSets of nodes
we were using in the fallback analysis with a single iterator. This
way we won't re-walk portions of the graph that are reached more than
once, and we also do less allocation etc.
@rust-log-analyzer

This comment has been minimized.

This avoids select_obligations_where_possible having an effect, which future
proofs the algorithm.
This doesn't yet fully work -- running coercions seems to be prone to causing
errors in the environment, which creates a little noise in some cases. It should
be enough to let us re-run crater, though, I think.
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-10 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
Some tests failed in compiletest suite=mir-opt mode=mir-opt host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu
..............................i.............F...................
failures:

---- [mir-opt] mir-opt/separate_const_switch.rs stdout ----
1 - // MIR for `identity` before SeparateConstSwitch
2 + // MIR for `identity` after SeparateConstSwitch
+   
+   
4   fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
5       debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
6       let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
15       scope 1 {
15       scope 1 {
16           debug residual => _6;            // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
17           scope 2 {
-               scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+               scope 8 (inlined <Result<i32, i32> as FromResidual<Result<!, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
19                   debug residual => _8;    // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
20                   let _16: i32;            // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
21                   let mut _17: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10

49               debug e => _13;              // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
51       }
- 
+   
53       bb0: {
53       bb0: {
54           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
55           StorageLive(_3);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10

60 -         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
61 +         switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
- 
+   
64       bb1: {
64       bb1: {
65 -         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
66 -         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10

67 -         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
68 -         switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
69 -     }
+ - 
71 -     bb2: {
71 -     bb2: {
72           StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
73           _9 = ((_3 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10

79           StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
80           return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
- 
+   
83 -     bb3: {
84 +     bb2: {
84 +     bb2: {
85           StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10

103           StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
104           return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
- 
+   
107 -     bb4: {
108 +     bb3: {
108 +     bb3: {
109           StorageLive(_13);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10

124 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
125 +         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
- 
+   
128 -     bb5: {
129 +     bb4: {
129 +     bb4: {
130           unreachable;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
131       }
- 
+   
133 -     bb6: {
133 -     bb6: {
134 +     bb5: {
135           StorageLive(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10

147 +         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
149   }
- 
+   
151 
151 

thread '[mir-opt] mir-opt/separate_const_switch.rs' panicked at 'Actual MIR output differs from expected MIR output /checkout/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff', src/tools/compiletest/src/runtest.rs:3588:25


failures:
    [mir-opt] mir-opt/separate_const_switch.rs
    [mir-opt] mir-opt/separate_const_switch.rs

test result: FAILED. 160 passed; 1 failed; 3 ignored; 0 measured; 0 filtered out; finished in 5.24s



command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/mir-opt" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/mir-opt" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--suite" "mir-opt" "--mode" "mir-opt" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-10/bin/FileCheck" "--nodejs" "/usr/bin/node" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python3" "--lldb-python" "/usr/bin/python3" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "10.0.0" "--llvm-components" "aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo amdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwriter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo cfguard codegen core coroutines coverage debuginfocodeview debuginfodwarf debuginfogsym debuginfomsf debuginfopdb demangle dlltooldriver dwarflinker engine executionengine frontendopenmp fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation interpreter ipo irreader jitlink lanai lanaiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo libdriver lineeditor linker lto mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts object objectyaml option orcerror orcjit passes perfjitevents powerpc powerpcasmparser powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvutils runtimedyld scalaropts selectiondag sparc sparcasmparser sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target textapi transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86utils xcore xcorecodegen xcoredesc xcoredisassembler xcoreinfo xray" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--channel" "nightly" "--color" "always"


Build completed unsuccessfully in 0:13:25

@jackh726
Copy link
Member

jackh726 commented Sep 2, 2021

@Mark-Simulacrum what's the plan here? Are you planning to split out some of this into more PRs? I can definitely try to review some, especially code that was mostly written by Niko :)

@Mark-Simulacrum
Copy link
Member Author

Yeah, the next steps are:

  • Split some more work out, probably, into smaller PRs -- likely will ask for your review on most of these
  • Document the algorithm in this PR (Niko's + some further adjustments since then)
  • T-lang discussion + potential stabilization report

@jackh726 jackh726 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 3, 2021
@Mark-Simulacrum Mark-Simulacrum added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 4, 2021
@Mark-Simulacrum
Copy link
Member Author

Going to go ahead and close this -- work is proceeding in #88804 and this isn't useful to keep open for now.

bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 23, 2021
…matsakis,jackh726

Revise never type fallback algorithm

This is a rebase of rust-lang#84573, but dropping the stabilization of never type (and the accompanying large test diff).

Each commit builds & has tests updated alongside it, and could be reviewed in a more or less standalone fashion. But it may make more sense to review the PR as a whole, I'm not sure. It should be noted that tests being updated isn't really a good indicator of final behavior -- never_type_fallback is not enabled by default in this PR, so we can't really see the full effects of the commits here.

This combines the work by Niko, which is [documented in this gist](https://gist.github.com/nikomatsakis/7a07b265dc12f5c3b3bd0422018fa660), with some additional rules largely derived to target specific known patterns that regress with the algorithm solely derived by Niko. We build these from an intuition that:

* In general, fallback to `()` is *sound* in all cases
* But, in general, we *prefer* fallback to `!` as it accepts more code, particularly that written to intentionally use `!` (e.g., Result's with a Infallible/! variant).

When evaluating Niko's proposed algorithm, we find that there are certain cases where fallback to `!` leads to compilation failures in real-world code, and fallback to `()` fixes those errors. In order to allow for stabilization, we need to fix a good portion of these patterns.

The final rule set this PR proposes is that, by default, we fallback from `?T` to `!`, with the following exceptions:

1. `?T: Foo` and `Bar::Baz = ?T` and `(): Foo`, then fallback to `()`
2. Per [Niko's algorithm](https://gist.github.com/nikomatsakis/7a07b265dc12f5c3b3bd0422018fa660#proposal-fallback-chooses-between--and--based-on-the-coercion-graph), the "live" `?T` also fallback to `()`.

The first rule is necessary to address a fairly common pattern which boils down to something like the snippet below. Without rule 1, we do not see the closure's return type as needing a () fallback, which leads to compilation failure.

```rust
#![feature(never_type_fallback)]

trait Bar { }
impl Bar for () {  }
impl Bar for u32 {  }

fn foo<R: Bar>(_: impl Fn() -> R) {}

fn main() {
    foo(|| panic!());
}
```

r? `@jackh726`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.