Skip to content

Commit

Permalink
Automatically taint InferCtxt when errors are emitted
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jun 26, 2024
1 parent 5988078 commit 86c8eae
Show file tree
Hide file tree
Showing 56 changed files with 601 additions and 570 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'_, '_, 'cx, 'tcx> {
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
let diag = unexpected_hidden_region_diagnostic(
self.infcx.tcx,
self.infcx,
self.mir_def_id(),
span,
named_ty,
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ impl<'tcx> InferCtxt<'tcx> {
}

if let Err(guar) =
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span)
{
return Ty::new_error(self.tcx, guar);
}
Expand All @@ -294,6 +294,10 @@ impl<'tcx> InferCtxt<'tcx> {
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
.ty;

if let Err(e) = definition_ty.error_reported() {
return Ty::new_error(self.tcx, e);
}

// `definition_ty` does not live in of the current inference context,
// so lets make sure that we don't accidentally misuse our current `infcx`.
match check_opaque_type_well_formed(
Expand Down Expand Up @@ -387,10 +391,11 @@ fn check_opaque_type_well_formed<'tcx>(
/// [rustc-dev-guide chapter]:
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
fn check_opaque_type_parameter_valid<'tcx>(
tcx: TyCtxt<'tcx>,
infcx: &InferCtxt<'tcx>,
opaque_type_key: OpaqueTypeKey<'tcx>,
span: Span,
) -> Result<(), ErrorGuaranteed> {
let tcx = infcx.tcx;
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
Expand Down Expand Up @@ -420,7 +425,7 @@ fn check_opaque_type_parameter_valid<'tcx>(

opaque_env.param_is_error(i)?;

return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
ty: arg,
kind,
span,
Expand All @@ -438,7 +443,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
.collect();
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
return Err(tcx
return Err(infcx
.dcx()
.struct_span_err(span, "non-defining opaque type use in defining scope")
.with_span_note(spans, format!("{descr} used multiple times"))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
// would be bad.
impl<G> !Clone for Diag<'_, G> {}

rustc_data_structures::static_assert_size!(Diag<'_, ()>, 2 * std::mem::size_of::<usize>());
rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * std::mem::size_of::<usize>());

impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
type Target = DiagInner;
Expand Down
61 changes: 41 additions & 20 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ use rustc_span::source_map::SourceMap;
use rustc_span::{Loc, Span, DUMMY_SP};
use std::backtrace::{Backtrace, BacktraceStatus};
use std::borrow::Cow;
use std::cell::Cell;
use std::error::Report;
use std::fmt;
use std::hash::Hash;
Expand Down Expand Up @@ -98,9 +99,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16);
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
pub enum SuggestionStyle {
Expand Down Expand Up @@ -417,6 +418,7 @@ pub struct DiagCtxt {
#[derive(Copy, Clone)]
pub struct DiagCtxtHandle<'a> {
dcx: &'a DiagCtxt,
tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
}

impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
Expand Down Expand Up @@ -752,7 +754,14 @@ impl DiagCtxt {
}

pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
DiagCtxtHandle { dcx: self }
DiagCtxtHandle { dcx: self, tainted_with_errors: None }
}

pub fn taintable_handle<'a>(
&'a self,
tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
) -> DiagCtxtHandle<'a> {
DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
}
}

Expand Down Expand Up @@ -795,7 +804,9 @@ impl<'a> DiagCtxtHandle<'a> {
// can be used to create a backtrace at the stashing site insted of whenever the
// diagnostic context is dropped and thus delayed bugs are emitted.
Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))),
DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
DelayedBug => {
return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
}
ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
| Expect(_) => None,
};
Expand Down Expand Up @@ -947,16 +958,19 @@ impl<'a> DiagCtxtHandle<'a> {
(0, _) => {
// Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a
// configuration like `--cap-lints allow --force-warn bare_trait_objects`.
inner.emit_diagnostic(DiagInner::new(
ForceWarning(None),
DiagMessage::Str(warnings),
));
inner.emit_diagnostic(
DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)),
None,
);
}
(_, 0) => {
inner.emit_diagnostic(DiagInner::new(Error, errors));
inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
}
(_, _) => {
inner.emit_diagnostic(DiagInner::new(Error, format!("{errors}; {warnings}")));
inner.emit_diagnostic(
DiagInner::new(Error, format!("{errors}; {warnings}")),
self.tainted_with_errors,
);
}
}

Expand Down Expand Up @@ -987,14 +1001,14 @@ impl<'a> DiagCtxtHandle<'a> {
"For more information about an error, try `rustc --explain {}`.",
&error_codes[0]
);
inner.emit_diagnostic(DiagInner::new(FailureNote, msg1));
inner.emit_diagnostic(DiagInner::new(FailureNote, msg2));
inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
} else {
let msg = format!(
"For more information about this error, try `rustc --explain {}`.",
&error_codes[0]
);
inner.emit_diagnostic(DiagInner::new(FailureNote, msg));
inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
}
}
}
Expand All @@ -1020,7 +1034,7 @@ impl<'a> DiagCtxtHandle<'a> {
}

pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
self.inner.borrow_mut().emit_diagnostic(diagnostic)
self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
}

pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
Expand Down Expand Up @@ -1080,7 +1094,7 @@ impl<'a> DiagCtxtHandle<'a> {
// Here the diagnostic is given back to `emit_diagnostic` where it was first
// intercepted. Now it should be processed as usual, since the unstable expectation
// id is now stable.
inner.emit_diagnostic(diag);
inner.emit_diagnostic(diag, self.tainted_with_errors);
}
}

Expand Down Expand Up @@ -1430,13 +1444,17 @@ impl DiagCtxtInner {
continue;
}
}
guar = guar.or(self.emit_diagnostic(diag));
guar = guar.or(self.emit_diagnostic(diag, None));
}
guar
}

// Return value is only `Some` if the level is `Error` or `DelayedBug`.
fn emit_diagnostic(&mut self, mut diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
fn emit_diagnostic(
&mut self,
mut diagnostic: DiagInner,
taint: Option<&Cell<Option<ErrorGuaranteed>>>,
) -> Option<ErrorGuaranteed> {
match diagnostic.level {
Expect(expect_id) | ForceWarning(Some(expect_id)) => {
// The `LintExpectationId` can be stable or unstable depending on when it was
Expand Down Expand Up @@ -1609,6 +1627,9 @@ impl DiagCtxtInner {
if is_lint {
self.lint_err_guars.push(guar);
} else {
if let Some(taint) = taint {
taint.set(Some(guar));
}
self.err_guars.push(guar);
}
self.panic_if_treat_err_as_bug();
Expand Down Expand Up @@ -1718,8 +1739,8 @@ impl DiagCtxtInner {
// `-Ztreat-err-as-bug`, which we don't want.
let note1 = "no errors encountered even though delayed bugs were created";
let note2 = "those delayed bugs will now be shown as internal compiler errors";
self.emit_diagnostic(DiagInner::new(Note, note1));
self.emit_diagnostic(DiagInner::new(Note, note2));
self.emit_diagnostic(DiagInner::new(Note, note1), None);
self.emit_diagnostic(DiagInner::new(Note, note2), None);

for bug in bugs {
if let Some(out) = &mut out {
Expand Down Expand Up @@ -1752,7 +1773,7 @@ impl DiagCtxtInner {
}
bug.level = Bug;

self.emit_diagnostic(bug);
self.emit_diagnostic(bug, None);
}

// Panic with `DelayedBugPanic` to avoid "unexpected panic" messages.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
} else {
errors::CannotCastToBoolHelp::Unsupported(self.span)
};
fcx.tcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
fcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
}
CastError::CastToChar => {
let mut err = type_error_struct!(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Set expectation to error in that case and set tainted
// by error (#114529)
let coerce_to = opt_coerce_to.unwrap_or_else(|| {
let guar = tcx.dcx().span_delayed_bug(
let guar = self.dcx().span_delayed_bug(
expr.span,
"illegal break with value found but no error reported",
);
Expand Down Expand Up @@ -1716,7 +1716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
error_happened = true;
let guar = if let Some(prev_span) = seen_fields.get(&ident) {
tcx.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
self.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
span: field.ident.span,
prev_span: *prev_span,
ident,
Expand Down Expand Up @@ -1757,7 +1757,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if adt_kind == AdtKind::Union {
if hir_fields.len() != 1 {
struct_span_code_err!(
tcx.dcx(),
self.dcx(),
span,
E0784,
"union expressions should have exactly one field",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
}

fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error {
self.tcx.dcx().span_delayed_bug(span, msg.to_string())
self.dcx().span_delayed_bug(span, msg.to_string())
}

fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error> {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
name: self.tcx.item_name(def.did()).to_ident_string(),
});
if ty.raw.has_param() {
let guar = self.tcx.dcx().emit_err(errors::SelfCtorFromOuterItem {
let guar = self.dcx().emit_err(errors::SelfCtorFromOuterItem {
span: path_span,
impl_span: tcx.def_span(impl_def_id),
sugg,
Expand All @@ -1207,7 +1207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check the visibility of the ctor.
let vis = tcx.visibility(ctor_def_id);
if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) {
tcx.dcx()
self.dcx()
.emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
}
let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
Expand All @@ -1216,7 +1216,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(new_res, Some(user_args.args))
}
_ => {
let mut err = tcx.dcx().struct_span_err(
let mut err = self.dcx().struct_span_err(
span,
"the `Self` constructor can only be used with tuple or unit structs",
);
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Otherwise, there's a mismatch, so clear out what we're expecting, and set
// our input types to err_args so we don't blow up the error messages
let guar = struct_span_code_err!(
tcx.dcx(),
self.dcx(),
call_span,
E0059,
"cannot use call notation; the first type parameter \
Expand Down Expand Up @@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.map(|vars| self.resolve_vars_if_possible(vars)),
);

self.set_tainted_by_errors(self.report_arg_errors(
self.report_arg_errors(
compatibility_diagonal,
formal_and_expected_inputs,
provided_args,
Expand All @@ -462,7 +462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_def_id,
call_span,
call_expr,
));
);
}
}

Expand Down Expand Up @@ -788,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("arguments to this {call_name} are incorrect"),
);
} else {
err = tcx.dcx().struct_span_err(
err = self.dcx().struct_span_err(
full_call_span,
format!(
"{call_name} takes {}{} but {} {} supplied",
Expand Down Expand Up @@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span_bug!(error_span, "expected errors from argument matrix");
} else {
let mut err =
tcx.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
suggest_confusable(&mut err);
return err.emit();
}
Expand Down Expand Up @@ -953,14 +953,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
struct_span_code_err!(
tcx.dcx(),
self.dcx(),
full_call_span,
E0308,
"arguments to this {} are incorrect",
call_name,
)
} else {
tcx.dcx()
self.dcx()
.struct_span_err(
full_call_span,
format!(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Note: this path is currently not reached in any test, so any
// example that triggers this would be worth minimizing and
// converting into a test.
tcx.dcx().span_bug(span, "argument to transmute has inference variables");
self.dcx().span_bug(span, "argument to transmute has inference variables");
}
// Transmutes that are only changing lifetimes are always ok.
if from == to {
Expand All @@ -76,7 +76,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
{
struct_span_code_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type")
struct_span_code_err!(self.dcx(), span, E0591, "can't transmute zero-sized type")
.with_note(format!("source type: {from}"))
.with_note(format!("target type: {to}"))
.with_help("cast with `as` to a pointer instead")
Expand Down Expand Up @@ -116,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

let mut err = struct_span_code_err!(
tcx.dcx(),
self.dcx(),
span,
E0512,
"cannot transmute between types of different sizes, \
Expand Down
Loading

0 comments on commit 86c8eae

Please sign in to comment.