Skip to content

Commit 86c8eae

Browse files
committed
Automatically taint InferCtxt when errors are emitted
1 parent 5988078 commit 86c8eae

File tree

56 files changed

+601
-570
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+601
-570
lines changed

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'_, '_, 'cx, 'tcx> {
360360
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
361361
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
362362
let diag = unexpected_hidden_region_diagnostic(
363-
self.infcx.tcx,
363+
self.infcx,
364364
self.mir_def_id(),
365365
span,
366366
named_ty,

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl<'tcx> InferCtxt<'tcx> {
285285
}
286286

287287
if let Err(guar) =
288-
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
288+
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span)
289289
{
290290
return Ty::new_error(self.tcx, guar);
291291
}
@@ -294,6 +294,10 @@ impl<'tcx> InferCtxt<'tcx> {
294294
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
295295
.ty;
296296

297+
if let Err(e) = definition_ty.error_reported() {
298+
return Ty::new_error(self.tcx, e);
299+
}
300+
297301
// `definition_ty` does not live in of the current inference context,
298302
// so lets make sure that we don't accidentally misuse our current `infcx`.
299303
match check_opaque_type_well_formed(
@@ -387,10 +391,11 @@ fn check_opaque_type_well_formed<'tcx>(
387391
/// [rustc-dev-guide chapter]:
388392
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
389393
fn check_opaque_type_parameter_valid<'tcx>(
390-
tcx: TyCtxt<'tcx>,
394+
infcx: &InferCtxt<'tcx>,
391395
opaque_type_key: OpaqueTypeKey<'tcx>,
392396
span: Span,
393397
) -> Result<(), ErrorGuaranteed> {
398+
let tcx = infcx.tcx;
394399
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
395400
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
396401
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
@@ -420,7 +425,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
420425

421426
opaque_env.param_is_error(i)?;
422427

423-
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
428+
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
424429
ty: arg,
425430
kind,
426431
span,
@@ -438,7 +443,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
438443
.collect();
439444
#[allow(rustc::diagnostic_outside_of_impl)]
440445
#[allow(rustc::untranslatable_diagnostic)]
441-
return Err(tcx
446+
return Err(infcx
442447
.dcx()
443448
.struct_span_err(span, "non-defining opaque type use in defining scope")
444449
.with_span_note(spans, format!("{descr} used multiple times"))

compiler/rustc_errors/src/diagnostic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
510510
// would be bad.
511511
impl<G> !Clone for Diag<'_, G> {}
512512

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

515515
impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
516516
type Target = DiagInner;

compiler/rustc_errors/src/lib.rs

+41-20
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ use rustc_span::source_map::SourceMap;
6363
use rustc_span::{Loc, Span, DUMMY_SP};
6464
use std::backtrace::{Backtrace, BacktraceStatus};
6565
use std::borrow::Cow;
66+
use std::cell::Cell;
6667
use std::error::Report;
6768
use std::fmt;
6869
use std::hash::Hash;
@@ -98,9 +99,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
9899

99100
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
100101
#[cfg(target_pointer_width = "64")]
101-
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
102+
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
102103
#[cfg(target_pointer_width = "64")]
103-
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16);
104+
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
104105

105106
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
106107
pub enum SuggestionStyle {
@@ -417,6 +418,7 @@ pub struct DiagCtxt {
417418
#[derive(Copy, Clone)]
418419
pub struct DiagCtxtHandle<'a> {
419420
dcx: &'a DiagCtxt,
421+
tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
420422
}
421423

422424
impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
@@ -752,7 +754,14 @@ impl DiagCtxt {
752754
}
753755

754756
pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
755-
DiagCtxtHandle { dcx: self }
757+
DiagCtxtHandle { dcx: self, tainted_with_errors: None }
758+
}
759+
760+
pub fn taintable_handle<'a>(
761+
&'a self,
762+
tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
763+
) -> DiagCtxtHandle<'a> {
764+
DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
756765
}
757766
}
758767

@@ -795,7 +804,9 @@ impl<'a> DiagCtxtHandle<'a> {
795804
// can be used to create a backtrace at the stashing site insted of whenever the
796805
// diagnostic context is dropped and thus delayed bugs are emitted.
797806
Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))),
798-
DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
807+
DelayedBug => {
808+
return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
809+
}
799810
ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
800811
| Expect(_) => None,
801812
};
@@ -947,16 +958,19 @@ impl<'a> DiagCtxtHandle<'a> {
947958
(0, _) => {
948959
// Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a
949960
// configuration like `--cap-lints allow --force-warn bare_trait_objects`.
950-
inner.emit_diagnostic(DiagInner::new(
951-
ForceWarning(None),
952-
DiagMessage::Str(warnings),
953-
));
961+
inner.emit_diagnostic(
962+
DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)),
963+
None,
964+
);
954965
}
955966
(_, 0) => {
956-
inner.emit_diagnostic(DiagInner::new(Error, errors));
967+
inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
957968
}
958969
(_, _) => {
959-
inner.emit_diagnostic(DiagInner::new(Error, format!("{errors}; {warnings}")));
970+
inner.emit_diagnostic(
971+
DiagInner::new(Error, format!("{errors}; {warnings}")),
972+
self.tainted_with_errors,
973+
);
960974
}
961975
}
962976

@@ -987,14 +1001,14 @@ impl<'a> DiagCtxtHandle<'a> {
9871001
"For more information about an error, try `rustc --explain {}`.",
9881002
&error_codes[0]
9891003
);
990-
inner.emit_diagnostic(DiagInner::new(FailureNote, msg1));
991-
inner.emit_diagnostic(DiagInner::new(FailureNote, msg2));
1004+
inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
1005+
inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
9921006
} else {
9931007
let msg = format!(
9941008
"For more information about this error, try `rustc --explain {}`.",
9951009
&error_codes[0]
9961010
);
997-
inner.emit_diagnostic(DiagInner::new(FailureNote, msg));
1011+
inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
9981012
}
9991013
}
10001014
}
@@ -1020,7 +1034,7 @@ impl<'a> DiagCtxtHandle<'a> {
10201034
}
10211035

10221036
pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
1023-
self.inner.borrow_mut().emit_diagnostic(diagnostic)
1037+
self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
10241038
}
10251039

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

@@ -1430,13 +1444,17 @@ impl DiagCtxtInner {
14301444
continue;
14311445
}
14321446
}
1433-
guar = guar.or(self.emit_diagnostic(diag));
1447+
guar = guar.or(self.emit_diagnostic(diag, None));
14341448
}
14351449
guar
14361450
}
14371451

14381452
// Return value is only `Some` if the level is `Error` or `DelayedBug`.
1439-
fn emit_diagnostic(&mut self, mut diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
1453+
fn emit_diagnostic(
1454+
&mut self,
1455+
mut diagnostic: DiagInner,
1456+
taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1457+
) -> Option<ErrorGuaranteed> {
14401458
match diagnostic.level {
14411459
Expect(expect_id) | ForceWarning(Some(expect_id)) => {
14421460
// The `LintExpectationId` can be stable or unstable depending on when it was
@@ -1609,6 +1627,9 @@ impl DiagCtxtInner {
16091627
if is_lint {
16101628
self.lint_err_guars.push(guar);
16111629
} else {
1630+
if let Some(taint) = taint {
1631+
taint.set(Some(guar));
1632+
}
16121633
self.err_guars.push(guar);
16131634
}
16141635
self.panic_if_treat_err_as_bug();
@@ -1718,8 +1739,8 @@ impl DiagCtxtInner {
17181739
// `-Ztreat-err-as-bug`, which we don't want.
17191740
let note1 = "no errors encountered even though delayed bugs were created";
17201741
let note2 = "those delayed bugs will now be shown as internal compiler errors";
1721-
self.emit_diagnostic(DiagInner::new(Note, note1));
1722-
self.emit_diagnostic(DiagInner::new(Note, note2));
1742+
self.emit_diagnostic(DiagInner::new(Note, note1), None);
1743+
self.emit_diagnostic(DiagInner::new(Note, note2), None);
17231744

17241745
for bug in bugs {
17251746
if let Some(out) = &mut out {
@@ -1752,7 +1773,7 @@ impl DiagCtxtInner {
17521773
}
17531774
bug.level = Bug;
17541775

1755-
self.emit_diagnostic(bug);
1776+
self.emit_diagnostic(bug, None);
17561777
}
17571778

17581779
// Panic with `DelayedBugPanic` to avoid "unexpected panic" messages.

compiler/rustc_hir_typeck/src/cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
319319
} else {
320320
errors::CannotCastToBoolHelp::Unsupported(self.span)
321321
};
322-
fcx.tcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
322+
fcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
323323
}
324324
CastError::CastToChar => {
325325
let mut err = type_error_struct!(

compiler/rustc_hir_typeck/src/expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
638638
// Set expectation to error in that case and set tainted
639639
// by error (#114529)
640640
let coerce_to = opt_coerce_to.unwrap_or_else(|| {
641-
let guar = tcx.dcx().span_delayed_bug(
641+
let guar = self.dcx().span_delayed_bug(
642642
expr.span,
643643
"illegal break with value found but no error reported",
644644
);
@@ -1716,7 +1716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17161716
} else {
17171717
error_happened = true;
17181718
let guar = if let Some(prev_span) = seen_fields.get(&ident) {
1719-
tcx.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
1719+
self.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
17201720
span: field.ident.span,
17211721
prev_span: *prev_span,
17221722
ident,
@@ -1757,7 +1757,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17571757
if adt_kind == AdtKind::Union {
17581758
if hir_fields.len() != 1 {
17591759
struct_span_code_err!(
1760-
tcx.dcx(),
1760+
self.dcx(),
17611761
span,
17621762
E0784,
17631763
"union expressions should have exactly one field",

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
170170
}
171171

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

176176
fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error> {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1182,7 +1182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11821182
name: self.tcx.item_name(def.did()).to_ident_string(),
11831183
});
11841184
if ty.raw.has_param() {
1185-
let guar = self.tcx.dcx().emit_err(errors::SelfCtorFromOuterItem {
1185+
let guar = self.dcx().emit_err(errors::SelfCtorFromOuterItem {
11861186
span: path_span,
11871187
impl_span: tcx.def_span(impl_def_id),
11881188
sugg,
@@ -1207,7 +1207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12071207
// Check the visibility of the ctor.
12081208
let vis = tcx.visibility(ctor_def_id);
12091209
if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) {
1210-
tcx.dcx()
1210+
self.dcx()
12111211
.emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
12121212
}
12131213
let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
@@ -1216,7 +1216,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12161216
(new_res, Some(user_args.args))
12171217
}
12181218
_ => {
1219-
let mut err = tcx.dcx().struct_span_err(
1219+
let mut err = self.dcx().struct_span_err(
12201220
span,
12211221
"the `Self` constructor can only be used with tuple or unit structs",
12221222
);

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
238238
// Otherwise, there's a mismatch, so clear out what we're expecting, and set
239239
// our input types to err_args so we don't blow up the error messages
240240
let guar = struct_span_code_err!(
241-
tcx.dcx(),
241+
self.dcx(),
242242
call_span,
243243
E0059,
244244
"cannot use call notation; the first type parameter \
@@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
453453
.map(|vars| self.resolve_vars_if_possible(vars)),
454454
);
455455

456-
self.set_tainted_by_errors(self.report_arg_errors(
456+
self.report_arg_errors(
457457
compatibility_diagonal,
458458
formal_and_expected_inputs,
459459
provided_args,
@@ -462,7 +462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
462462
fn_def_id,
463463
call_span,
464464
call_expr,
465-
));
465+
);
466466
}
467467
}
468468

@@ -788,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
788788
format!("arguments to this {call_name} are incorrect"),
789789
);
790790
} else {
791-
err = tcx.dcx().struct_span_err(
791+
err = self.dcx().struct_span_err(
792792
full_call_span,
793793
format!(
794794
"{call_name} takes {}{} but {} {} supplied",
@@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
848848
span_bug!(error_span, "expected errors from argument matrix");
849849
} else {
850850
let mut err =
851-
tcx.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
851+
self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
852852
suggest_confusable(&mut err);
853853
return err.emit();
854854
}
@@ -953,14 +953,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
953953

954954
let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
955955
struct_span_code_err!(
956-
tcx.dcx(),
956+
self.dcx(),
957957
full_call_span,
958958
E0308,
959959
"arguments to this {} are incorrect",
960960
call_name,
961961
)
962962
} else {
963-
tcx.dcx()
963+
self.dcx()
964964
.struct_span_err(
965965
full_call_span,
966966
format!(

compiler/rustc_hir_typeck/src/intrinsicck.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5252
// Note: this path is currently not reached in any test, so any
5353
// example that triggers this would be worth minimizing and
5454
// converting into a test.
55-
tcx.dcx().span_bug(span, "argument to transmute has inference variables");
55+
self.dcx().span_bug(span, "argument to transmute has inference variables");
5656
}
5757
// Transmutes that are only changing lifetimes are always ok.
5858
if from == to {
@@ -76,7 +76,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7676
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
7777
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
7878
{
79-
struct_span_code_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type")
79+
struct_span_code_err!(self.dcx(), span, E0591, "can't transmute zero-sized type")
8080
.with_note(format!("source type: {from}"))
8181
.with_note(format!("target type: {to}"))
8282
.with_help("cast with `as` to a pointer instead")
@@ -116,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
116116
};
117117

118118
let mut err = struct_span_code_err!(
119-
tcx.dcx(),
119+
self.dcx(),
120120
span,
121121
E0512,
122122
"cannot transmute between types of different sizes, \

0 commit comments

Comments
 (0)