Skip to content

Commit c2e1ae4

Browse files
committedJul 12, 2023
typeck: taint if errors found during writeback
If any type added to the `TypeckResults` references an error then set tainted by errors. By doing this, const eval can be skipped on bodies that reference errors which would make const eval ICE. Signed-off-by: David Wood <david@davidtw.co>
1 parent 2b6d6e1 commit c2e1ae4

6 files changed

+107
-1
lines changed
 

‎compiler/rustc_hir_typeck/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,8 @@ hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead
9494
hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
9595
9696
hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
97+
98+
hir_typeck_writeback_found_err = found type error in writeback
99+
97100
hir_typeck_yield_expr_outside_of_generator =
98101
yield expression outside of generator literal

‎compiler/rustc_hir_typeck/src/writeback.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// unresolved type variables and replaces "ty_var" types with their
33
// substitutions.
44

5-
use crate::FnCtxt;
5+
use crate::{fluent_generated as fluent, FnCtxt};
66
use hir::def_id::LocalDefId;
77
use rustc_data_structures::fx::FxHashMap;
88
use rustc_errors::{ErrorGuaranteed, StashKey};
@@ -134,13 +134,34 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
134134
self.fcx.tcx
135135
}
136136

137+
/// Checks if `ty` contains a `ty::Error` (i.e. `ty.references_error()`), but peering into
138+
/// function signatures and ADTs.
139+
fn deep_references_error(&self, ty: Ty<'tcx>) -> bool {
140+
ty.references_error() || {
141+
match ty.kind() {
142+
ty::Adt(adt, substs) => {
143+
adt.all_fields().any(|field| field.ty(self.tcx(), substs).references_error())
144+
}
145+
ty::FnDef(..) => ty.fn_sig(self.tcx()).references_error(),
146+
_ => false,
147+
}
148+
}
149+
}
150+
137151
fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
138152
debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
139153
assert!(
140154
!ty.has_infer() && !ty.has_placeholders() && !ty.has_free_regions(),
141155
"{ty} can't be put into typeck results"
142156
);
143157
self.typeck_results.node_types_mut().insert(hir_id, ty);
158+
if self.deep_references_error(ty) {
159+
self.typeck_results.tainted_by_errors = Some(
160+
self.tcx()
161+
.sess
162+
.delay_span_bug(rustc_span::DUMMY_SP, fluent::hir_typeck_writeback_found_err),
163+
);
164+
}
144165
}
145166

146167
// Hacky hack: During type-checking, we treat *all* operators
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pub struct Opcode(pub u8);
2+
3+
pub struct Opcode2 {
4+
s: &'a S,
5+
//~^ ERROR cannot find type `S` in this scope [E0412]
6+
//~^^ ERROR use of undeclared lifetime name `'a` [E0261]
7+
}
8+
9+
impl Opcode2 {
10+
pub const OP2: Opcode2 = Opcode2 { s: Opcode(0x1) };
11+
}
12+
13+
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
14+
move |i| match msg_type {
15+
Opcode2::OP2 => unimplemented!(),
16+
}
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0261]: use of undeclared lifetime name `'a`
2+
--> $DIR/issue-112824-type-mismatch-type-error-1.rs:4:9
3+
|
4+
LL | pub struct Opcode2 {
5+
| - help: consider introducing lifetime `'a` here: `<'a>`
6+
LL | s: &'a S,
7+
| ^^ undeclared lifetime
8+
9+
error[E0412]: cannot find type `S` in this scope
10+
--> $DIR/issue-112824-type-mismatch-type-error-1.rs:4:12
11+
|
12+
LL | s: &'a S,
13+
| ^ not found in this scope
14+
|
15+
help: you might be missing a type parameter
16+
|
17+
LL | pub struct Opcode2<S> {
18+
| +++
19+
20+
error: aborting due to 2 previous errors
21+
22+
Some errors have detailed explanations: E0261, E0412.
23+
For more information about an error, try `rustc --explain E0261`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pub struct Opcode(pub u8);
2+
3+
pub struct Opcode2(&'a S);
4+
//~^ ERROR cannot find type `S` in this scope [E0412]
5+
//~^^ ERROR use of undeclared lifetime name `'a` [E0261]
6+
7+
impl Opcode2 {
8+
pub const OP2: Opcode2 = Opcode2(Opcode(0x1));
9+
}
10+
11+
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
12+
move |i| match msg_type {
13+
Opcode2::OP2 => unimplemented!(),
14+
}
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0261]: use of undeclared lifetime name `'a`
2+
--> $DIR/issue-112824-type-mismatch-type-error.rs:3:21
3+
|
4+
LL | pub struct Opcode2(&'a S);
5+
| - ^^ undeclared lifetime
6+
| |
7+
| help: consider introducing lifetime `'a` here: `<'a>`
8+
9+
error[E0412]: cannot find type `S` in this scope
10+
--> $DIR/issue-112824-type-mismatch-type-error.rs:3:24
11+
|
12+
LL | pub struct Opcode2(&'a S);
13+
| ^ not found in this scope
14+
|
15+
help: you might be missing a type parameter
16+
|
17+
LL | pub struct Opcode2<S>(&'a S);
18+
| +++
19+
20+
error: aborting due to 2 previous errors
21+
22+
Some errors have detailed explanations: E0261, E0412.
23+
For more information about an error, try `rustc --explain E0261`.

0 commit comments

Comments
 (0)
Please sign in to comment.