mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #123571 - WaffleLapkin:properly-adjust-never, 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 #123482's crater run. r? compiler-errors Fixes #120600
This commit is contained in:
commit
6c4657c086
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
//@ known-bug: #120600
|
||||
#![feature(never_type, never_type_fallback)]
|
||||
|
||||
enum E { Bar(!) }
|
||||
|
||||
fn f(a: &E, b: &E) {
|
||||
match (a, b) {
|
||||
(E::Bar(a), E::Bar(b)) => { *a == *b; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
@ -1,11 +0,0 @@
|
||||
//@ known-bug: #120600
|
||||
#![feature(never_type)]
|
||||
#![feature(never_type_fallback)]
|
||||
|
||||
#[derive(Ord, Eq, PartialOrd, PartialEq)]
|
||||
enum E {
|
||||
Foo,
|
||||
Bar(!, i32, i32),
|
||||
}
|
||||
|
||||
fn main() {}
|
53
tests/mir-opt/building/eq_never_type._f.built.after.mir
Normal file
53
tests/mir-opt/building/eq_never_type._f.built.after.mir
Normal file
@ -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
tests/mir-opt/building/eq_never_type.rs
Normal file
13
tests/mir-opt/building/eq_never_type.rs
Normal file
@ -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
tests/ui/never_type/eq-never-types.rs
Normal file
13
tests/ui/never_type/eq-never-types.rs
Normal file
@ -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() {}
|
Loading…
Reference in New Issue
Block a user