Skip to content

Commit 513e9a7

Browse files
authored
Rollup merge of rust-lang#120972 - lukas-code:autoderef-type-error, r=compiler-errors
fix ICE for deref coercions with type errors Follow-up to rust-lang#120895, where I made types with errors go through the full coercion code, which is necessary if we want to build MIR for bodies with errors (rust-lang#120550). The code for coercing `&T` to `&U` currently assumes that autoderef for `&T` will succeed for at least two steps (`&T` and `T`): https://github.com/rust-lang/rust/blob/b17491c8f6d555386104dfd82004c01bfef09c95/compiler/rustc_hir_typeck/src/coercion.rs#L339-L464 But for types with errors, we previously only returned the no-op autoderef step (`&{type error}` -> `&{type error}`) and then stopped early. This PR changes autoderef for types with errors to still go through the built-in derefs (e.g. `&&{type error}` -> `&{type error}` -> `{type error}`) and only stop early when it would have to go looking for `Deref` trait impls. fixes rust-lang#120945 r? `@compiler-errors` or compiler
2 parents ec0d48b + 95c5b06 commit 513e9a7

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

compiler/rustc_hir_analysis/src/autoderef.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
9191
return None;
9292
};
9393

94-
if new_ty.references_error() {
95-
return None;
96-
}
97-
9894
self.state.steps.push((self.state.cur_ty, kind));
9995
debug!(
10096
"autoderef stage #{:?} is {:?} from {:?}",
@@ -137,6 +133,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
137133
debug!("overloaded_deref_ty({:?})", ty);
138134
let tcx = self.infcx.tcx;
139135

136+
if ty.references_error() {
137+
return None;
138+
}
139+
140140
// <ty as Deref>
141141
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
142142
let cause = traits::ObligationCause::misc(self.span, self.body_id);

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,12 @@ fn check_method_receiver<'tcx>(
16351635
let receiver_ty = sig.inputs()[0];
16361636
let receiver_ty = wfcx.normalize(span, None, receiver_ty);
16371637

1638+
// If the receiver already has errors reported, consider it valid to avoid
1639+
// unnecessary errors (#58712).
1640+
if receiver_ty.references_error() {
1641+
return Ok(());
1642+
}
1643+
16381644
if tcx.features().arbitrary_self_types {
16391645
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
16401646
// Report error; `arbitrary_self_types` was enabled.
@@ -1749,9 +1755,7 @@ fn receiver_is_valid<'tcx>(
17491755
}
17501756
} else {
17511757
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
1752-
// If the receiver already has errors reported due to it, consider it valid to avoid
1753-
// unnecessary errors (#58712).
1754-
return receiver_ty.references_error();
1758+
return false;
17551759
}
17561760
}
17571761

tests/ui/coercion/type-errors.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
// Regression test for an ICE: https://github.com/rust-lang/rust/issues/120884
1+
// Test that we don't ICE for coercions with type errors.
22
// We still need to properly go through coercions between types with errors instead of
33
// shortcutting and returning success, because we need the adjustments for building the MIR.
44

55
pub fn has_error() -> TypeError {}
66
//~^ ERROR cannot find type `TypeError` in this scope
77

8+
// https://github.com/rust-lang/rust/issues/120884
9+
// Casting a function item to a data pointer in valid in HIR, but invalid in MIR.
10+
// We need an adjustment (ReifyFnPointer) to insert a cast from the function item
11+
// to a function pointer as a separate MIR statement.
812
pub fn cast() -> *const u8 {
9-
// Casting a function item to a data pointer in valid in HIR, but invalid in MIR.
10-
// We need an adjustment (ReifyFnPointer) to insert a cast from the function item
11-
// to a function pointer as a separate MIR statement.
1213
has_error as *const u8
1314
}
1415

16+
// https://github.com/rust-lang/rust/issues/120945
17+
// This one ICEd, because we skipped the builtin deref from `&TypeError` to `TypeError`.
18+
pub fn autoderef_source(e: &TypeError) {
19+
//~^ ERROR cannot find type `TypeError` in this scope
20+
autoderef_target(e)
21+
}
22+
23+
pub fn autoderef_target(_: &TypeError) {}
24+
//~^ ERROR cannot find type `TypeError` in this scope
25+
1526
fn main() {}

tests/ui/coercion/type-errors.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ error[E0412]: cannot find type `TypeError` in this scope
44
LL | pub fn has_error() -> TypeError {}
55
| ^^^^^^^^^ not found in this scope
66

7-
error: aborting due to 1 previous error
7+
error[E0412]: cannot find type `TypeError` in this scope
8+
--> $DIR/type-errors.rs:18:29
9+
|
10+
LL | pub fn autoderef_source(e: &TypeError) {
11+
| ^^^^^^^^^ not found in this scope
12+
13+
error[E0412]: cannot find type `TypeError` in this scope
14+
--> $DIR/type-errors.rs:23:29
15+
|
16+
LL | pub fn autoderef_target(_: &TypeError) {}
17+
| ^^^^^^^^^ not found in this scope
18+
19+
error: aborting due to 3 previous errors
820

921
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)