|
2 | 2 | // unresolved type variables and replaces "ty_var" types with their
|
3 | 3 | // substitutions.
|
4 | 4 |
|
5 |
| -use crate::FnCtxt; |
| 5 | +use crate::{fluent_generated as fluent, FnCtxt}; |
6 | 6 | use hir::def_id::LocalDefId;
|
7 | 7 | use rustc_data_structures::fx::FxHashMap;
|
8 | 8 | use rustc_errors::{ErrorGuaranteed, StashKey};
|
@@ -134,13 +134,34 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
134 | 134 | self.fcx.tcx
|
135 | 135 | }
|
136 | 136 |
|
| 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 | + |
137 | 151 | fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
|
138 | 152 | debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
|
139 | 153 | assert!(
|
140 | 154 | !ty.has_infer() && !ty.has_placeholders() && !ty.has_free_regions(),
|
141 | 155 | "{ty} can't be put into typeck results"
|
142 | 156 | );
|
143 | 157 | 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 | + } |
144 | 165 | }
|
145 | 166 |
|
146 | 167 | // Hacky hack: During type-checking, we treat *all* operators
|
|
0 commit comments