Skip to content

Commit

Permalink
Rollup merge of rust-lang#123571 - WaffleLapkin:properly-adjust-never…
Browse files Browse the repository at this point in the history
…, r=compiler-errors

Correctly change type when adding adjustments on top of `NeverToAny`

I'm concerned that the check only caught the problem with `fallback = !`, because at least MIR contained `<() as PartialEq>::eq(move _5, move _7)` where `_5: ()`.

I rediscovered the issue when looking at rust-lang#123482's crater run.

r? compiler-errors
Fixes rust-lang#120600
  • Loading branch information
matthiaskrgr committed Apr 19, 2024
2 parents 07d0d7c + e5a6d8d commit 43852d0
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 34 deletions.
33 changes: 23 additions & 10 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)), .. },
],
Expand All @@ -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!(
Expand All @@ -308,9 +320,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
adj
),
);

*entry.get_mut() = adj;
}
}
*entry.get_mut() = adj;
}
}

Expand Down
13 changes: 0 additions & 13 deletions tests/crashes/120600-2.rs

This file was deleted.

11 changes: 0 additions & 11 deletions tests/crashes/120600.rs

This file was deleted.

53 changes: 53 additions & 0 deletions tests/mir-opt/building/eq_never_type._f.built.after.mir
Original file line number Diff line number Diff line change
@@ -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;
}
}
13 changes: 13 additions & 0 deletions tests/mir-opt/building/eq_never_type.rs
Original file line number Diff line number Diff line change
@@ -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() {}
13 changes: 13 additions & 0 deletions tests/ui/never_type/eq-never-types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//@ check-pass
//
// issue: rust-lang/rust#120600

#![allow(internal_features)]
#![feature(never_type, rustc_attrs)]
#![rustc_never_type_options(fallback = "never")]

fn ice(a: !) {
a == a;
}

fn main() {}

0 comments on commit 43852d0

Please sign in to comment.