From bbd359fc6e51c7bd23d90eb4aa935a81bbb5d979 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 6 Apr 2024 17:18:25 +0000 Subject: [PATCH 1/3] Add regression test for issue 120600 --- tests/ui/never_type/eq-never-types.rs | 22 ++++++++++++++++++++++ tests/ui/never_type/eq-never-types.stderr | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/ui/never_type/eq-never-types.rs create mode 100644 tests/ui/never_type/eq-never-types.stderr diff --git a/tests/ui/never_type/eq-never-types.rs b/tests/ui/never_type/eq-never-types.rs new file mode 100644 index 0000000000000..00e55c100bdd3 --- /dev/null +++ b/tests/ui/never_type/eq-never-types.rs @@ -0,0 +1,22 @@ +//@ known-bug: #120600 +// +// issue: rust-lang/rust#120600 + +//@ failure-status: 101 +//@ normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" +//@ normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> "" +//@ normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> "" +//@ normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> "" +//@ normalize-stderr-test: "(?m)note: delayed at.*$" -> "" +//@ normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" +//@ normalize-stderr-test: "(?m)^ *at .*\n" -> "" + +#![allow(internal_features)] +#![feature(never_type, rustc_attrs)] +#![rustc_never_type_options(fallback = "never")] + +fn ice(a: !) { + a == a; +} + +fn main() {} diff --git a/tests/ui/never_type/eq-never-types.stderr b/tests/ui/never_type/eq-never-types.stderr new file mode 100644 index 0000000000000..61c3f430b9a5d --- /dev/null +++ b/tests/ui/never_type/eq-never-types.stderr @@ -0,0 +1,20 @@ +note: no errors encountered even though delayed bugs were created + +note: those delayed bugs will now be shown as internal compiler errors + +error: internal compiler error: broken MIR in DefId(ice) (Terminator { source_info: SourceInfo { span: $DIR/eq-never-types.rs:19:5: 19:11 (#0), scope: scope[0] }, kind: _3 = ::eq(move _4, move _5) -> [return: bb1, unwind: bb2] }): bad arg #0 (&'?4 ! <- !): NoSolution + --> $DIR/eq-never-types.rs:19:10 + | +LL | a == a; + | ^ + | + + --> $DIR/eq-never-types.rs:19:10 + | +LL | a == a; + | ^ + +note: using internal features is not supported and expected to cause internal compiler errors when used incorrectly + +query stack during panic: +end of query stack From 17371626e7e793f8edac2115c0a7f10c93568b33 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 6 Apr 2024 20:29:36 +0000 Subject: [PATCH 2/3] Add a test for `a == b` where `a: !, b: !` (this currently produces malformed mir: we call `eq` with first argument not being a reference) --- .../building/eq_never_type._f.built.after.mir | 53 +++++++++++++++++++ tests/mir-opt/building/eq_never_type.rs | 13 +++++ 2 files changed, 66 insertions(+) create mode 100644 tests/mir-opt/building/eq_never_type._f.built.after.mir create mode 100644 tests/mir-opt/building/eq_never_type.rs diff --git a/tests/mir-opt/building/eq_never_type._f.built.after.mir b/tests/mir-opt/building/eq_never_type._f.built.after.mir new file mode 100644 index 0000000000000..29e93a29aab4b --- /dev/null +++ b/tests/mir-opt/building/eq_never_type._f.built.after.mir @@ -0,0 +1,53 @@ +// MIR for `_f` after built + +fn _f(_1: !, _2: !) -> () { + debug a => _1; + debug b => _2; + let mut _0: (); + let mut _3: !; + let _4: bool; + let mut _5: (); + let mut _6: !; + let mut _7: &(); + let _8: (); + let mut _9: !; + + bb0: { + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _6 = _1; + unreachable; + } + + bb1: { + StorageDead(_6); + StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + _9 = _2; + unreachable; + } + + bb2: { + _7 = &_8; + StorageDead(_9); + _4 = <() as PartialEq>::eq(move _5, move _7) -> [return: bb3, unwind: bb5]; + } + + bb3: { + StorageDead(_7); + StorageDead(_5); + StorageDead(_8); + StorageDead(_4); + unreachable; + } + + bb4: { + return; + } + + bb5 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/eq_never_type.rs b/tests/mir-opt/building/eq_never_type.rs new file mode 100644 index 0000000000000..90e2e69753531 --- /dev/null +++ b/tests/mir-opt/building/eq_never_type.rs @@ -0,0 +1,13 @@ +// skip-filecheck +#![feature(never_type)] +#![allow(unreachable_code)] + +// EMIT_MIR eq_never_type._f.built.after.mir +fn _f(a: !, b: !) { + // Both arguments must be references (i.e. == should auto-borrow/coerce-to-ref both arguments) + // (this previously was buggy due to `NeverToAny` coercion incorrectly throwing out other + // coercions) + a == b; +} + +fn main() {} From 62d956fde5350da099acb760a790df3eb04e6e74 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 6 Apr 2024 20:52:32 +0000 Subject: [PATCH 3/3] Correctly change type when adding adjustments on top of `NeverToAny` --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 33 +++++++++++++------ .../building/eq_never_type._f.built.after.mir | 2 +- tests/ui/never_type/eq-never-types.rs | 11 +------ tests/ui/never_type/eq-never-types.stderr | 20 ----------- 4 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 tests/ui/never_type/eq-never-types.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 85d04f7d1c41e..e02f88708f879 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -279,13 +279,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Entry::Occupied(mut entry) => { debug!(" - composing on top of {:?}", entry.get()); - match (&entry.get()[..], &adj[..]) { - // Applying any adjustment on top of a NeverToAny - // is a valid NeverToAny adjustment, because it can't - // be reached. - (&[Adjustment { kind: Adjust::NeverToAny, .. }], _) => return, + match (&mut entry.get_mut()[..], &adj[..]) { ( - &[ + [Adjustment { kind: Adjust::NeverToAny, target }], + &[.., Adjustment { target: new_target, .. }], + ) => { + // NeverToAny coercion can target any type, so instead of adding a new + // adjustment on top we can change the target. + // + // This is required for things like `a == a` (where `a: !`) to produce + // valid MIR -- we need borrow adjustment from things like `==` to change + // the type to `&!` (or `&()` depending on the fallback). This might be + // relevant even in unreachable code. + *target = new_target; + } + + ( + &mut [ Adjustment { kind: Adjust::Deref(_), .. }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, ], @@ -294,11 +304,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .., // Any following adjustments are allowed. ], ) => { - // A reborrow has no effect before a dereference. + // A reborrow has no effect before a dereference, so we can safely replace adjustments. + *entry.get_mut() = adj; } - // FIXME: currently we never try to compose autoderefs - // and ReifyFnPointer/UnsafeFnPointer, but we could. + _ => { + // FIXME: currently we never try to compose autoderefs + // and ReifyFnPointer/UnsafeFnPointer, but we could. self.dcx().span_delayed_bug( expr.span, format!( @@ -308,9 +320,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adj ), ); + + *entry.get_mut() = adj; } } - *entry.get_mut() = adj; } } diff --git a/tests/mir-opt/building/eq_never_type._f.built.after.mir b/tests/mir-opt/building/eq_never_type._f.built.after.mir index 29e93a29aab4b..39438258c2ebb 100644 --- a/tests/mir-opt/building/eq_never_type._f.built.after.mir +++ b/tests/mir-opt/building/eq_never_type._f.built.after.mir @@ -6,7 +6,7 @@ fn _f(_1: !, _2: !) -> () { let mut _0: (); let mut _3: !; let _4: bool; - let mut _5: (); + let mut _5: &(); let mut _6: !; let mut _7: &(); let _8: (); diff --git a/tests/ui/never_type/eq-never-types.rs b/tests/ui/never_type/eq-never-types.rs index 00e55c100bdd3..19717fcf4433c 100644 --- a/tests/ui/never_type/eq-never-types.rs +++ b/tests/ui/never_type/eq-never-types.rs @@ -1,16 +1,7 @@ -//@ known-bug: #120600 +//@ check-pass // // issue: rust-lang/rust#120600 -//@ failure-status: 101 -//@ normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//@ normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> "" -//@ normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> "" -//@ normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> "" -//@ normalize-stderr-test: "(?m)note: delayed at.*$" -> "" -//@ normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" -//@ normalize-stderr-test: "(?m)^ *at .*\n" -> "" - #![allow(internal_features)] #![feature(never_type, rustc_attrs)] #![rustc_never_type_options(fallback = "never")] diff --git a/tests/ui/never_type/eq-never-types.stderr b/tests/ui/never_type/eq-never-types.stderr deleted file mode 100644 index 61c3f430b9a5d..0000000000000 --- a/tests/ui/never_type/eq-never-types.stderr +++ /dev/null @@ -1,20 +0,0 @@ -note: no errors encountered even though delayed bugs were created - -note: those delayed bugs will now be shown as internal compiler errors - -error: internal compiler error: broken MIR in DefId(ice) (Terminator { source_info: SourceInfo { span: $DIR/eq-never-types.rs:19:5: 19:11 (#0), scope: scope[0] }, kind: _3 = ::eq(move _4, move _5) -> [return: bb1, unwind: bb2] }): bad arg #0 (&'?4 ! <- !): NoSolution - --> $DIR/eq-never-types.rs:19:10 - | -LL | a == a; - | ^ - | - - --> $DIR/eq-never-types.rs:19:10 - | -LL | a == a; - | ^ - -note: using internal features is not supported and expected to cause internal compiler errors when used incorrectly - -query stack during panic: -end of query stack