diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 3d012a15a675b..6986d13bc76a4 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -94,5 +94,8 @@ hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field + +hir_typeck_writeback_found_err = found type error in writeback + hir_typeck_yield_expr_outside_of_generator = yield expression outside of generator literal diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9a80a9c9303e3..6c27a49936b13 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -467,7 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn node_ty_opt(&self, id: hir::HirId) -> Option> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => Some(t), - None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx,e)), + None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx, e)), None => None, } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 10645753609a0..c18d57d2ddaad 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -2,7 +2,7 @@ // unresolved type variables and replaces "ty_var" types with their // substitutions. -use crate::FnCtxt; +use crate::{fluent_generated as fluent, FnCtxt}; use hir::def_id::LocalDefId; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ErrorGuaranteed, StashKey}; @@ -134,6 +134,20 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.fcx.tcx } + /// Checks if `ty` contains a `ty::Error` (i.e. `ty.references_error()`), but peering into + /// function signatures and ADTs. + fn deep_references_error(&self, ty: Ty<'tcx>) -> bool { + ty.references_error() || { + match ty.kind() { + ty::Adt(adt, substs) => { + adt.all_fields().any(|field| field.ty(self.tcx(), substs).references_error()) + } + ty::FnDef(..) => ty.fn_sig(self.tcx()).references_error(), + _ => false, + } + } + } + fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) { debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty); assert!( @@ -141,6 +155,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { "{ty} can't be put into typeck results" ); self.typeck_results.node_types_mut().insert(hir_id, ty); + if self.deep_references_error(ty) { + self.typeck_results.tainted_by_errors = Some( + self.tcx() + .sess + .delay_span_bug(rustc_span::DUMMY_SP, fluent::hir_typeck_writeback_found_err), + ); + } } // Hacky hack: During type-checking, we treat *all* operators diff --git a/tests/ui/cast/issue-112630-1.rs b/tests/ui/cast/issue-112630-1.rs new file mode 100644 index 0000000000000..c392f3ad4436d --- /dev/null +++ b/tests/ui/cast/issue-112630-1.rs @@ -0,0 +1,6 @@ +fn f(_: B) {} +//~^ ERROR cannot find type `B` in this scope [E0412] + +fn main() { + let _ = [0; f as usize]; +} diff --git a/tests/ui/cast/issue-112630-1.stderr b/tests/ui/cast/issue-112630-1.stderr new file mode 100644 index 0000000000000..79adb7c6ce6a0 --- /dev/null +++ b/tests/ui/cast/issue-112630-1.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `B` in this scope + --> $DIR/issue-112630-1.rs:1:9 + | +LL | fn f(_: B) {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn f(_: B) {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/cast/issue-112630.rs b/tests/ui/cast/issue-112630.rs new file mode 100644 index 0000000000000..abae887b9a490 --- /dev/null +++ b/tests/ui/cast/issue-112630.rs @@ -0,0 +1,8 @@ +enum Foo { + Bar(B), + //~^ ERROR cannot find type `B` in this scope [E0412] +} + +fn main() { + let _ = [0; Foo::Bar as usize]; +} diff --git a/tests/ui/cast/issue-112630.stderr b/tests/ui/cast/issue-112630.stderr new file mode 100644 index 0000000000000..04910fc557756 --- /dev/null +++ b/tests/ui/cast/issue-112630.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `B` in this scope + --> $DIR/issue-112630.rs:2:9 + | +LL | Bar(B), + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | enum Foo { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs new file mode 100644 index 0000000000000..edbf4eb8f6928 --- /dev/null +++ b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs @@ -0,0 +1,19 @@ +pub struct Opcode(pub u8); + +pub struct Opcode2 { + s: &'a S, + //~^ ERROR cannot find type `S` in this scope [E0412] + //~^^ ERROR use of undeclared lifetime name `'a` [E0261] +} + +impl Opcode2 { + pub const OP2: Opcode2 = Opcode2 { s: Opcode(0x1) }; +} + +pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { + move |i| match msg_type { + Opcode2::OP2 => unimplemented!(), + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr new file mode 100644 index 0000000000000..68362788545b9 --- /dev/null +++ b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr @@ -0,0 +1,23 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-112824-type-mismatch-type-error-1.rs:4:9 + | +LL | pub struct Opcode2 { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | s: &'a S, + | ^^ undeclared lifetime + +error[E0412]: cannot find type `S` in this scope + --> $DIR/issue-112824-type-mismatch-type-error-1.rs:4:12 + | +LL | s: &'a S, + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | pub struct Opcode2 { + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0412. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error.rs b/tests/ui/consts/issue-112824-type-mismatch-type-error.rs new file mode 100644 index 0000000000000..018dfbba185fb --- /dev/null +++ b/tests/ui/consts/issue-112824-type-mismatch-type-error.rs @@ -0,0 +1,17 @@ +pub struct Opcode(pub u8); + +pub struct Opcode2(&'a S); +//~^ ERROR cannot find type `S` in this scope [E0412] +//~^^ ERROR use of undeclared lifetime name `'a` [E0261] + +impl Opcode2 { + pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); +} + +pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { + move |i| match msg_type { + Opcode2::OP2 => unimplemented!(), + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr b/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr new file mode 100644 index 0000000000000..7ebd5ad30accb --- /dev/null +++ b/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr @@ -0,0 +1,23 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-112824-type-mismatch-type-error.rs:3:21 + | +LL | pub struct Opcode2(&'a S); + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0412]: cannot find type `S` in this scope + --> $DIR/issue-112824-type-mismatch-type-error.rs:3:24 + | +LL | pub struct Opcode2(&'a S); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | pub struct Opcode2(&'a S); + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0412. +For more information about an error, try `rustc --explain E0261`.