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

Automatically taint InferCtxt when errors are emitted #126996

Merged
merged 8 commits into from
Jul 1, 2024
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);
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
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>>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments, please! This needs some explanation.

}

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
Loading