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

This commit is contained in:
Maybe Waffle 2024-04-06 20:52:32 +00:00
parent 4d749cad25
commit 0bbe362901
4 changed files with 25 additions and 41 deletions

View File

@ -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;
}
}

View File

@ -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: ();

View File

@ -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")]

View File

@ -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 = <! as PartialEq>::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