Skip to content

Commit

Permalink
check type error recursively in typeck
Browse files Browse the repository at this point in the history
  • Loading branch information
adwinwhite committed Aug 5, 2024
1 parent 176e545 commit d5a99f3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
45 changes: 44 additions & 1 deletion compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ mod typeck_root_ctxt;
mod upvar;
mod writeback;

use core::ops::ControlFlow;

pub use coercion::can_coerce;
use fn_ctxt::FnCtxt;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed};
Expand All @@ -55,7 +58,7 @@ use rustc_hir_analysis::check::check_abi;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_middle::{bug, span_bug};
use rustc_session::config;
use rustc_span::def_id::LocalDefId;
Expand Down Expand Up @@ -116,6 +119,41 @@ pub fn inspect_typeck<'tcx>(
typeck_with_fallback(tcx, def_id, fallback, Some(inspect))
}

struct RecursiveHasErrorVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
// To avoid cycle when visiting recursive types.
visited_tys: FxHashSet<Ty<'tcx>>,
}

impl<'tcx> RecursiveHasErrorVisitor<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> Self {
RecursiveHasErrorVisitor { tcx, visited_tys: Default::default() }
}
}

impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for RecursiveHasErrorVisitor<'tcx> {
type Result = ControlFlow<ErrorGuaranteed>;

fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
self.visited_tys.insert(t.clone());
if let ty::Adt(def, args) = t.kind() {
let field_tys: Vec<_> = def.all_fields().map(|f| f.ty(self.tcx, args)).collect();
for field_ty in field_tys {
if !self.visited_tys.contains(&field_ty) {
// Force early return with `Break`.
// Visitors don't bail by default.
field_ty.visit_with(self)?;
}
}
}
t.super_visit_with(self)
}

fn visit_error(&mut self, guar: ErrorGuaranteed) -> Self::Result {
ControlFlow::Break(guar)
}
}

#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)]
fn typeck_with_fallback<'tcx>(
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -168,6 +206,11 @@ fn typeck_with_fallback<'tcx>(

let expected_type = fcx.normalize(body.value.span, expected_type);

let mut error_visitor = RecursiveHasErrorVisitor::new(tcx);
if let ControlFlow::Break(guar) = expected_type.visit_with(&mut error_visitor) {
fcx.set_tainted_by_errors(guar);
}

let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);

Expand Down
13 changes: 13 additions & 0 deletions tests/ui/typeck/wide_ptr_transmute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// issue #127742
struct Vtable(dyn Cap);
//~^ ERROR missing lifetime specifier

trait Cap<'a> {}

union Transmute {
t: u64,
u: &'static Vtable,
}

const G: &'static Vtable = unsafe { Transmute { t: 1 }.u };
fn main() {}
19 changes: 19 additions & 0 deletions tests/ui/typeck/wide_ptr_transmute.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0106]: missing lifetime specifier
--> $DIR/wide_ptr_transmute.rs:2:19
|
LL | struct Vtable(dyn Cap);
| ^^^ expected named lifetime parameter
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | struct Vtable(dyn for<'a> Cap<'a>);
| +++++++ ++++
help: consider introducing a named lifetime parameter
|
LL | struct Vtable<'a>(dyn Cap<'a>);
| ++++ ++++

error: aborting due to 1 previous error

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

0 comments on commit d5a99f3

Please sign in to comment.