Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typeck: taint if errors found during writeback #113125

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
davidtwco marked this conversation as resolved.
Show resolved Hide resolved

hir_typeck_yield_expr_outside_of_generator =
yield expression outside of generator literal
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
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,
}
}
Expand Down
23 changes: 22 additions & 1 deletion compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -134,13 +134,34 @@ 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!(
!ty.has_infer() && !ty.has_placeholders() && !ty.has_free_regions(),
"{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
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/cast/issue-112630-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn f(_: B) {}
//~^ ERROR cannot find type `B` in this scope [E0412]

fn main() {
let _ = [0; f as usize];
}
14 changes: 14 additions & 0 deletions tests/ui/cast/issue-112630-1.stderr
Original file line number Diff line number Diff line change
@@ -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>(_: B) {}
| +++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0412`.
8 changes: 8 additions & 0 deletions tests/ui/cast/issue-112630.rs
Original file line number Diff line number Diff line change
@@ -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];
}
14 changes: 14 additions & 0 deletions tests/ui/cast/issue-112630.stderr
Original file line number Diff line number Diff line change
@@ -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<B> {
| +++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0412`.
19 changes: 19 additions & 0 deletions tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs
Original file line number Diff line number Diff line change
@@ -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() {}
23 changes: 23 additions & 0 deletions tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr
Original file line number Diff line number Diff line change
@@ -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<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`.
17 changes: 17 additions & 0 deletions tests/ui/consts/issue-112824-type-mismatch-type-error.rs
Original file line number Diff line number Diff line change
@@ -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() {}
23 changes: 23 additions & 0 deletions tests/ui/consts/issue-112824-type-mismatch-type-error.stderr
Original file line number Diff line number Diff line change
@@ -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<S>(&'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`.