1
Fork 0

rustc_error: make ErrorReported impossible to construct

There are a few places were we have to construct it, though, and a few
places that are more invasive to change. To do this, we create a
constructor with a long obvious name.
This commit is contained in:
mark 2022-01-22 18:49:12 -06:00
parent 461e807801
commit bb8d4307eb
104 changed files with 705 additions and 550 deletions

View file

@ -952,7 +952,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
sess.diagnostic().delay_span_bug( sess.diagnostic().delay_span_bug(
span, span,
"unexpected delimiter in key-value attribute's value", "unexpected delimiter in key-value attribute's value",
) );
} }
unwrap_single_token(sess, tokens, span) unwrap_single_token(sess, tokens, span)
} }

View file

@ -440,7 +440,7 @@ impl<'a> AstValidator<'a> {
attr.span, attr.span,
"allow, cfg, cfg_attr, deny, \ "allow, cfg, cfg_attr, deny, \
forbid, and warn are the only allowed built-in attributes in function parameters", forbid, and warn are the only allowed built-in attributes in function parameters",
) );
} }
}); });
} }

View file

@ -252,11 +252,12 @@ impl<'a> PostExpansionVisitor<'a> {
"wasm ABI is experimental and subject to change" "wasm ABI is experimental and subject to change"
); );
} }
abi => self abi => {
.sess self.sess.parse_sess.span_diagnostic.delay_span_bug(
.parse_sess span,
.span_diagnostic &format!("unrecognized ABI not caught in lowering: {}", abi),
.delay_span_bug(span, &format!("unrecognized ABI not caught in lowering: {}", abi)), );
}
} }
} }

View file

@ -178,7 +178,7 @@ fn do_mir_borrowck<'a, 'tcx>(
// Gather the upvars of a closure, if any. // Gather the upvars of a closure, if any.
let tables = tcx.typeck_opt_const_arg(def); let tables = tcx.typeck_opt_const_arg(def);
if let Some(ErrorGuaranteed) = tables.tainted_by_errors { if let Some(ErrorGuaranteed { .. }) = tables.tainted_by_errors {
infcx.set_tainted_by_errors(); infcx.set_tainted_by_errors();
errors.set_tainted_by_errors(); errors.set_tainted_by_errors();
} }
@ -2274,6 +2274,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
mod error { mod error {
use rustc_errors::ErrorGuaranteed;
use super::*; use super::*;
pub struct BorrowckErrors<'tcx> { pub struct BorrowckErrors<'tcx> {
@ -2311,7 +2313,7 @@ mod error {
// FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is // FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is
// set before any emission actually happens (weakening the guarantee). // set before any emission actually happens (weakening the guarantee).
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
self.tainted_by_errors = Some(ErrorGuaranteed {}); self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
t.buffer(&mut self.buffered); t.buffer(&mut self.buffered);
} }
@ -2320,7 +2322,7 @@ mod error {
} }
pub fn set_tainted_by_errors(&mut self) { pub fn set_tainted_by_errors(&mut self) {
self.tainted_by_errors = Some(ErrorGuaranteed {}); self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
} }
} }

View file

@ -1,7 +1,6 @@
//! Handling of `static`s, `const`s and promoted allocations //! Handling of `static`s, `const`s and promoted allocations
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::ErrorGuaranteed;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
@ -54,7 +53,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
{ {
all_constants_ok = false; all_constants_ok = false;
match err { match err {
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => { ErrorHandled::Reported(_) | ErrorHandled::Linted => {
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered"); fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
} }
ErrorHandled::TooGeneric => { ErrorHandled::TooGeneric => {

View file

@ -1,5 +1,4 @@
use crate::traits::*; use crate::traits::*;
use rustc_errors::ErrorGuaranteed;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
@ -191,7 +190,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
all_consts_ok = false; all_consts_ok = false;
match err { match err {
// errored or at least linted // errored or at least linted
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {} ErrorHandled::Reported(_) | ErrorHandled::Linted => {}
ErrorHandled::TooGeneric => { ErrorHandled::TooGeneric => {
span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err) span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err)
} }

View file

@ -1,4 +1,3 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
@ -247,11 +246,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
if ecx.tcx.is_ctfe_mir_available(def.did) { if ecx.tcx.is_ctfe_mir_available(def.did) {
Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def)) Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
} else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst { } else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst {
ecx.tcx.sess.delay_span_bug( let guar = ecx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP, rustc_span::DUMMY_SP,
"This is likely a const item that is missing from its impl", "This is likely a const item that is missing from its impl",
); );
throw_inval!(AlreadyReported(ErrorGuaranteed {})); throw_inval!(AlreadyReported(guar));
} else { } else {
let path = ecx.tcx.def_path_str(def.did); let path = ecx.tcx.def_path_str(def.did);
Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path)) Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path))

View file

@ -406,8 +406,11 @@ pub fn intern_const_alloc_recursive<
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
// Codegen does not like dangling pointers, and generally `tcx` assumes that // Codegen does not like dangling pointers, and generally `tcx` assumes that
// all allocations referenced anywhere actually exist. So, make sure we error here. // all allocations referenced anywhere actually exist. So, make sure we error here.
ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant"); let reported = ecx
return Err(ErrorGuaranteed); .tcx
.sess
.span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
return Err(reported);
} else if ecx.tcx.get_global_alloc(alloc_id).is_none() { } else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
// We have hit an `AllocId` that is neither in local or global memory and isn't // We have hit an `AllocId` that is neither in local or global memory and isn't
// marked as dangling by local memory. That should be impossible. // marked as dangling by local memory. That should be impossible.

View file

@ -4,12 +4,11 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::Write; use std::fmt::Write;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_macros::HashStable; use rustc_macros::HashStable;
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
use rustc_middle::ty::{ConstInt, Ty}; use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty};
use rustc_middle::{mir, ty}; use rustc_middle::{mir, ty};
use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
use rustc_target::abi::{VariantIdx, Variants}; use rustc_target::abi::{VariantIdx, Variants};
@ -565,7 +564,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
match val.val() { match val.val() {
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorGuaranteed)), ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
throw_inval!(AlreadyReported(reported))
}
ty::ConstKind::Unevaluated(uv) => { ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.substs)?; let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())

View file

@ -259,7 +259,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
self.tcx.sess.diagnostic().emit_diagnostic(&error); self.tcx.sess.diagnostic().emit_diagnostic(&error);
} }
} else { } else {
assert!(self.tcx.sess.has_errors()); assert!(self.tcx.sess.has_errors().is_some());
} }
} }
@ -327,8 +327,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
match op.importance() { match op.importance() {
ops::DiagnosticImportance::Primary => { ops::DiagnosticImportance::Primary => {
self.error_emitted = Some(ErrorGuaranteed); let reported = err.emit();
err.emit(); self.error_emitted = Some(reported);
} }
ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors), ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),

View file

@ -235,7 +235,7 @@ fn run_compiler(
}; };
match make_input(config.opts.error_format, &matches.free) { match make_input(config.opts.error_format, &matches.free) {
Err(ErrorGuaranteed) => return Err(ErrorGuaranteed), Err(reported) => return Err(reported),
Ok(Some((input, input_file_path))) => { Ok(Some((input, input_file_path))) => {
config.input = input; config.input = input;
config.input_path = input_file_path; config.input_path = input_file_path;
@ -465,11 +465,11 @@ fn make_input(
if io::stdin().read_to_string(&mut src).is_err() { if io::stdin().read_to_string(&mut src).is_err() {
// Immediately stop compilation if there was an issue reading // Immediately stop compilation if there was an issue reading
// the input (for example if the input stream is not UTF-8). // the input (for example if the input stream is not UTF-8).
early_error_no_abort( let reported = early_error_no_abort(
error_format, error_format,
"couldn't read from stdin, as it did not contain valid UTF-8", "couldn't read from stdin, as it did not contain valid UTF-8",
); );
return Err(ErrorGuaranteed); return Err(reported);
} }
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect( let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
@ -1128,7 +1128,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> { pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
if value.is::<rustc_errors::FatalErrorMarker>() { if value.is::<rustc_errors::FatalErrorMarker>() {
ErrorGuaranteed ErrorGuaranteed::unchecked_claim_error_was_emitted()
} else { } else {
panic::resume_unwind(value); panic::resume_unwind(value);
} }

View file

@ -128,7 +128,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
DiagnosticBuilderState::Emittable(handler) => { DiagnosticBuilderState::Emittable(handler) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
handler.emit_diagnostic(&db.inner.diagnostic); let guar = handler.emit_diagnostic(&db.inner.diagnostic);
// Only allow a guarantee if the `level` wasn't switched to a // Only allow a guarantee if the `level` wasn't switched to a
// non-error - the field isn't `pub`, but the whole `Diagnostic` // non-error - the field isn't `pub`, but the whole `Diagnostic`
@ -139,7 +139,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
from `DiagnosticBuilder<ErrorGuaranteed>`", from `DiagnosticBuilder<ErrorGuaranteed>`",
db.inner.diagnostic.level, db.inner.diagnostic.level,
); );
ErrorGuaranteed guar.unwrap()
} }
// `.emit()` was previously called, disallowed from repeating it, // `.emit()` was previously called, disallowed from repeating it,
// but can take advantage of the previous `.emit()`'s guarantee // but can take advantage of the previous `.emit()`'s guarantee
@ -154,7 +154,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
became non-error ({:?}), after original `.emit()`", became non-error ({:?}), after original `.emit()`",
db.inner.diagnostic.level, db.inner.diagnostic.level,
); );
ErrorGuaranteed ErrorGuaranteed::unchecked_claim_error_was_emitted()
} }
} }
} }

View file

@ -399,7 +399,7 @@ impl fmt::Display for ExplicitBug {
impl error::Error for ExplicitBug {} impl error::Error for ExplicitBug {}
pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic}; pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
pub use diagnostic_builder::DiagnosticBuilder; pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
use std::backtrace::Backtrace; use std::backtrace::Backtrace;
/// A handler deals with errors and other compiler output. /// A handler deals with errors and other compiler output.
@ -644,8 +644,8 @@ impl Handler {
} }
/// Emit all stashed diagnostics. /// Emit all stashed diagnostics.
pub fn emit_stashed_diagnostics(&self) { pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
self.inner.borrow_mut().emit_stashed_diagnostics(); self.inner.borrow_mut().emit_stashed_diagnostics()
} }
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
@ -805,8 +805,8 @@ impl Handler {
FatalError.raise() FatalError.raise()
} }
pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) { pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span); self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
} }
pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) { pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
@ -829,7 +829,7 @@ impl Handler {
} }
#[track_caller] #[track_caller]
pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) { pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
self.inner.borrow_mut().delay_span_bug(span, msg) self.inner.borrow_mut().delay_span_bug(span, msg)
} }
@ -858,8 +858,8 @@ impl Handler {
self.inner.borrow_mut().fatal(msg) self.inner.borrow_mut().fatal(msg)
} }
pub fn err(&self, msg: &str) { pub fn err(&self, msg: &str) -> ErrorGuaranteed {
self.inner.borrow_mut().err(msg); self.inner.borrow_mut().err(msg)
} }
pub fn warn(&self, msg: &str) { pub fn warn(&self, msg: &str) {
@ -880,11 +880,15 @@ impl Handler {
self.inner.borrow().err_count() self.inner.borrow().err_count()
} }
pub fn has_errors(&self) -> bool { pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
self.inner.borrow().has_errors() if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
}
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
if self.inner.borrow().has_errors_or_lint_errors() {
Some(ErrorGuaranteed(()))
} else {
None
} }
pub fn has_errors_or_lint_errors(&self) -> bool {
self.inner.borrow().has_errors_or_lint_errors()
} }
pub fn has_errors_or_delayed_span_bugs(&self) -> bool { pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
self.inner.borrow().has_errors_or_delayed_span_bugs() self.inner.borrow().has_errors_or_delayed_span_bugs()
@ -915,13 +919,17 @@ impl Handler {
self.inner.borrow_mut().force_print_diagnostic(db) self.inner.borrow_mut().force_print_diagnostic(db)
} }
pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) { pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
self.inner.borrow_mut().emit_diagnostic(diagnostic) self.inner.borrow_mut().emit_diagnostic(diagnostic)
} }
fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) { fn emit_diag_at_span(
&self,
mut diag: Diagnostic,
sp: impl Into<MultiSpan>,
) -> Option<ErrorGuaranteed> {
let mut inner = self.inner.borrow_mut(); let mut inner = self.inner.borrow_mut();
inner.emit_diagnostic(diag.set_span(sp)); inner.emit_diagnostic(diag.set_span(sp))
} }
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
@ -990,13 +998,20 @@ impl HandlerInner {
} }
/// Emit all stashed diagnostics. /// Emit all stashed diagnostics.
fn emit_stashed_diagnostics(&mut self) { fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>(); let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
diags.iter().for_each(|diag| self.emit_diagnostic(diag)); let mut reported = None;
diags.iter().for_each(|diag| {
if diag.is_error() {
reported = Some(ErrorGuaranteed(()));
}
self.emit_diagnostic(diag);
});
reported
} }
// FIXME(eddyb) this should ideally take `diagnostic` by value. // FIXME(eddyb) this should ideally take `diagnostic` by value.
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) { fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
if diagnostic.level == Level::DelayedBug { if diagnostic.level == Level::DelayedBug {
// FIXME(eddyb) this should check for `has_errors` and stop pushing // FIXME(eddyb) this should check for `has_errors` and stop pushing
// once *any* errors were emitted (and truncate `delayed_span_bugs` // once *any* errors were emitted (and truncate `delayed_span_bugs`
@ -1005,7 +1020,7 @@ impl HandlerInner {
self.delayed_span_bugs.push(diagnostic.clone()); self.delayed_span_bugs.push(diagnostic.clone());
if !self.flags.report_delayed_bugs { if !self.flags.report_delayed_bugs {
return; return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
} }
} }
@ -1020,7 +1035,7 @@ impl HandlerInner {
if diagnostic.has_future_breakage() { if diagnostic.has_future_breakage() {
(*TRACK_DIAGNOSTICS)(diagnostic); (*TRACK_DIAGNOSTICS)(diagnostic);
} }
return; return None;
} }
// The `LintExpectationId` can be stable or unstable depending on when it was created. // The `LintExpectationId` can be stable or unstable depending on when it was created.
@ -1029,16 +1044,16 @@ impl HandlerInner {
// a stable one by the `LintLevelsBuilder`. // a stable one by the `LintLevelsBuilder`.
if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level { if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
self.unstable_expect_diagnostics.push(diagnostic.clone()); self.unstable_expect_diagnostics.push(diagnostic.clone());
return; return None;
} }
(*TRACK_DIAGNOSTICS)(diagnostic); (*TRACK_DIAGNOSTICS)(diagnostic);
if let Level::Expect(expectation_id) = diagnostic.level { if let Level::Expect(expectation_id) = diagnostic.level {
self.fulfilled_expectations.insert(expectation_id); self.fulfilled_expectations.insert(expectation_id);
return; return None;
} else if diagnostic.level == Allow { } else if diagnostic.level == Allow {
return; return None;
} }
if let Some(ref code) = diagnostic.code { if let Some(ref code) = diagnostic.code {
@ -1068,8 +1083,12 @@ impl HandlerInner {
} else { } else {
self.bump_err_count(); self.bump_err_count();
} }
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else { } else {
self.bump_warn_count(); self.bump_warn_count();
None
} }
} }
@ -1191,7 +1210,7 @@ impl HandlerInner {
} }
#[track_caller] #[track_caller]
fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) { fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
// incrementing `err_count` by one, so we need to +1 the comparing. // incrementing `err_count` by one, so we need to +1 the comparing.
// FIXME: Would be nice to increment err_count in a more coherent way. // FIXME: Would be nice to increment err_count in a more coherent way.
@ -1202,7 +1221,7 @@ impl HandlerInner {
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
diagnostic.set_span(sp.into()); diagnostic.set_span(sp.into());
diagnostic.note(&format!("delayed at {}", std::panic::Location::caller())); diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
self.emit_diagnostic(&diagnostic) self.emit_diagnostic(&diagnostic).unwrap()
} }
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
@ -1221,20 +1240,20 @@ impl HandlerInner {
} }
fn fatal(&mut self, msg: &str) -> FatalError { fn fatal(&mut self, msg: &str) -> FatalError {
self.emit_error(Fatal, msg); self.emit(Fatal, msg);
FatalError FatalError
} }
fn err(&mut self, msg: &str) { fn err(&mut self, msg: &str) -> ErrorGuaranteed {
self.emit_error(Error { lint: false }, msg); self.emit(Error { lint: false }, msg)
} }
/// Emit an error; level should be `Error` or `Fatal`. /// Emit an error; level should be `Error` or `Fatal`.
fn emit_error(&mut self, level: Level, msg: &str) { fn emit(&mut self, level: Level, msg: &str) -> ErrorGuaranteed {
if self.treat_err_as_bug() { if self.treat_err_as_bug() {
self.bug(msg); self.bug(msg);
} }
self.emit_diagnostic(&Diagnostic::new(level, msg)); self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap()
} }
fn bug(&mut self, msg: &str) -> ! { fn bug(&mut self, msg: &str) -> ! {
@ -1433,9 +1452,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
); );
} }
// Useful type to use with `Result<>` indicate that an error has already /// Useful type to use with `Result<>` indicate that an error has already
// been reported to the user, so no need to continue checking. /// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ErrorGuaranteed; pub struct ErrorGuaranteed(());
impl ErrorGuaranteed {
/// To be used only if you really know what you are doing... ideally, we would find a way to
/// eliminate all calls to this method.
pub fn unchecked_claim_error_was_emitted() -> Self {
ErrorGuaranteed(())
}
}
rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed); rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);

View file

@ -1330,7 +1330,7 @@ pub fn parse_macro_name_and_helper_attrs(
let attributes_attr = list.get(1); let attributes_attr = list.get(1);
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.has_name(sym::attributes) { if !attr.has_name(sym::attributes) {
diag.span_err(attr.span(), "second argument must be `attributes`") diag.span_err(attr.span(), "second argument must be `attributes`");
} }
attr.meta_item_list() attr.meta_item_list()
.unwrap_or_else(|| { .unwrap_or_else(|| {

View file

@ -534,10 +534,10 @@ pub fn compile_declarative_macro(
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules); let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
match transparency_error { match transparency_error {
Some(TransparencyError::UnknownTransparency(value, span)) => { Some(TransparencyError::UnknownTransparency(value, span)) => {
diag.span_err(span, &format!("unknown macro transparency: `{}`", value)) diag.span_err(span, &format!("unknown macro transparency: `{}`", value));
} }
Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => { Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => {
diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes") diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes");
} }
None => {} None => {}
} }
@ -617,7 +617,9 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
match *rhs { match *rhs {
mbe::TokenTree::Delimited(..) => return true, mbe::TokenTree::Delimited(..) => return true,
_ => sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"), _ => {
sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited");
}
} }
false false
} }

View file

@ -31,8 +31,7 @@ impl base::ProcMacro for BangProcMacro {
if let Some(s) = e.as_str() { if let Some(s) = e.as_str() {
err.help(&format!("message: {}", s)); err.help(&format!("message: {}", s));
} }
err.emit(); err.emit()
ErrorGuaranteed
}) })
} }
} }
@ -58,8 +57,7 @@ impl base::AttrProcMacro for AttrProcMacro {
if let Some(s) = e.as_str() { if let Some(s) = e.as_str() {
err.help(&format!("message: {}", s)); err.help(&format!("message: {}", s));
} }
err.emit(); err.emit()
ErrorGuaranteed
}) })
} }
} }

View file

@ -225,12 +225,12 @@ pub fn prepare_session_directory(
let crate_dir = match crate_dir.canonicalize() { let crate_dir = match crate_dir.canonicalize() {
Ok(v) => v, Ok(v) => v,
Err(err) => { Err(err) => {
sess.err(&format!( let reported = sess.err(&format!(
"incremental compilation: error canonicalizing path `{}`: {}", "incremental compilation: error canonicalizing path `{}`: {}",
crate_dir.display(), crate_dir.display(),
err err
)); ));
return Err(ErrorGuaranteed); return Err(reported);
} }
}; };
@ -489,14 +489,14 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
sess.err(&format!( let reported = sess.err(&format!(
"Could not create incremental compilation {} \ "Could not create incremental compilation {} \
directory `{}`: {}", directory `{}`: {}",
dir_tag, dir_tag,
path.display(), path.display(),
err err
)); ));
Err(ErrorGuaranteed) Err(reported)
} }
} }
} }
@ -545,8 +545,7 @@ fn lock_directory(
); );
} }
} }
err.emit(); Err(err.emit())
Err(ErrorGuaranteed)
} }
} }
} }

View file

@ -147,8 +147,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err); self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
err.emit(); let reported = err.emit();
Some(ErrorGuaranteed) Some(reported)
} }
fn suggest_adding_lifetime_params( fn suggest_adding_lifetime_params(

View file

@ -98,7 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let impl_span = self.tcx().def_span(*impl_def_id); let impl_span = self.tcx().def_span(*impl_def_id);
err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
} }
err.emit(); let reported = err.emit();
Some(ErrorGuaranteed) Some(reported)
} }
} }

View file

@ -54,10 +54,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
pub fn try_report(&self) -> Option<ErrorGuaranteed> { pub fn try_report(&self) -> Option<ErrorGuaranteed> {
self.try_report_from_nll() self.try_report_from_nll()
.map(|mut diag| { .map(|mut diag| diag.emit())
diag.emit();
ErrorGuaranteed
})
.or_else(|| self.try_report_impl_not_conforming_to_trait()) .or_else(|| self.try_report_impl_not_conforming_to_trait())
.or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_anon_anon_conflict())
.or_else(|| self.try_report_static_impl_trait()) .or_else(|| self.try_report_static_impl_trait())

View file

@ -84,8 +84,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
), ),
); );
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
err.emit(); let reported = err.emit();
return Some(ErrorGuaranteed); return Some(reported);
} else { } else {
err.cancel(); err.cancel();
} }
@ -276,8 +276,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
Some((param.param_ty_span, param.param_ty.to_string())), Some((param.param_ty_span, param.param_ty.to_string())),
); );
err.emit(); let reported = err.emit();
Some(ErrorGuaranteed) Some(reported)
} }
} }

View file

@ -33,13 +33,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code()) ) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
&& sup_expected_found == sub_expected_found && sup_expected_found == sub_expected_found
{ {
self.emit_err( let guar = self.emit_err(
var_origin.span(), var_origin.span(),
sub_expected, sub_expected,
sub_found, sub_found,
*trait_item_def_id, *trait_item_def_id,
); );
return Some(ErrorGuaranteed); return Some(guar);
} }
if let RegionResolutionError::ConcreteFailure(origin, _, _) if let RegionResolutionError::ConcreteFailure(origin, _, _)
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone() | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
@ -49,18 +49,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
trait_item_def_id, trait_item_def_id,
} = origin } = origin
{ {
self.emit_associated_type_err( let guar = self.emit_associated_type_err(
span, span,
self.infcx.tcx.item_name(impl_item_def_id), self.infcx.tcx.item_name(impl_item_def_id),
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,
); );
return Some(ErrorGuaranteed); return Some(guar);
} }
None None
} }
fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) { fn emit_err(
&self,
sp: Span,
expected: Ty<'tcx>,
found: Ty<'tcx>,
trait_def_id: DefId,
) -> ErrorGuaranteed {
let trait_sp = self.tcx().def_span(trait_def_id); let trait_sp = self.tcx().def_span(trait_def_id);
let mut err = self let mut err = self
.tcx() .tcx()
@ -142,7 +148,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
argument, the other inputs and its output", argument, the other inputs and its output",
); );
} }
err.emit(); err.emit()
} }
fn emit_associated_type_err( fn emit_associated_type_err(
@ -151,7 +157,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
item_name: Symbol, item_name: Symbol,
impl_item_def_id: DefId, impl_item_def_id: DefId,
trait_item_def_id: DefId, trait_item_def_id: DefId,
) { ) -> ErrorGuaranteed {
let impl_sp = self.tcx().def_span(impl_item_def_id); let impl_sp = self.tcx().def_span(impl_item_def_id);
let trait_sp = self.tcx().def_span(trait_item_def_id); let trait_sp = self.tcx().def_span(trait_item_def_id);
let mut err = self let mut err = self
@ -161,7 +167,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
err.span_label(impl_sp, "found"); err.span_label(impl_sp, "found");
err.span_label(trait_sp, "expected"); err.span_label(trait_sp, "expected");
err.emit(); err.emit()
} }
} }

View file

@ -189,7 +189,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
self.tcx.sess.delay_span_bug( self.tcx.sess.delay_span_bug(
origin.span(), origin.span(),
&format!("no region-bound-pairs for {:?}", body_id), &format!("no region-bound-pairs for {:?}", body_id),
) );
} }
} }
} }

View file

@ -373,7 +373,7 @@ pub fn configure_and_expand(
if recursion_limit_hit { if recursion_limit_hit {
// If we hit a recursion limit, exit early to avoid later passes getting overwhelmed // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
// with a large AST // with a large AST
Err(ErrorGuaranteed) Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else { } else {
Ok(krate) Ok(krate)
} }
@ -413,7 +413,7 @@ pub fn configure_and_expand(
); );
msg.warn("The generated documentation may be incorrect"); msg.warn("The generated documentation may be incorrect");
msg.emit() msg.emit();
} else { } else {
krate = sess.time("maybe_create_a_macro_crate", || { krate = sess.time("maybe_create_a_macro_crate", || {
let is_test_crate = sess.opts.test; let is_test_crate = sess.opts.test;
@ -742,29 +742,30 @@ pub fn prepare_outputs(
if let Some(ref input_path) = compiler.input_path { if let Some(ref input_path) = compiler.input_path {
if sess.opts.will_create_output_file() { if sess.opts.will_create_output_file() {
if output_contains_path(&output_paths, input_path) { if output_contains_path(&output_paths, input_path) {
sess.err(&format!( let reported = sess.err(&format!(
"the input file \"{}\" would be overwritten by the generated \ "the input file \"{}\" would be overwritten by the generated \
executable", executable",
input_path.display() input_path.display()
)); ));
return Err(ErrorGuaranteed); return Err(reported);
} }
if let Some(dir_path) = output_conflicts_with_dir(&output_paths) { if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
sess.err(&format!( let reported = sess.err(&format!(
"the generated executable for the input file \"{}\" conflicts with the \ "the generated executable for the input file \"{}\" conflicts with the \
existing directory \"{}\"", existing directory \"{}\"",
input_path.display(), input_path.display(),
dir_path.display() dir_path.display()
)); ));
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
} }
if let Some(ref dir) = compiler.temps_dir { if let Some(ref dir) = compiler.temps_dir {
if fs::create_dir_all(dir).is_err() { if fs::create_dir_all(dir).is_err() {
let reported =
sess.err("failed to find or create the directory specified by `--temps-dir`"); sess.err("failed to find or create the directory specified by `--temps-dir`");
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
@ -776,8 +777,9 @@ pub fn prepare_outputs(
if !only_dep_info { if !only_dep_info {
if let Some(ref dir) = compiler.output_dir { if let Some(ref dir) = compiler.output_dir {
if fs::create_dir_all(dir).is_err() { if fs::create_dir_all(dir).is_err() {
let reported =
sess.err("failed to find or create the directory specified by `--out-dir`"); sess.err("failed to find or create the directory specified by `--out-dir`");
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
} }
@ -987,8 +989,8 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
// lot of annoying errors in the ui tests (basically, // lot of annoying errors in the ui tests (basically,
// lint warnings and so on -- kindck used to do this abort, but // lint warnings and so on -- kindck used to do this abort, but
// kindck is gone now). -nmatsakis // kindck is gone now). -nmatsakis
if sess.has_errors() { if let Some(reported) = sess.has_errors() {
return Err(ErrorGuaranteed); return Err(reported);
} }
sess.time("misc_checking_3", || { sess.time("misc_checking_3", || {

View file

@ -5,7 +5,6 @@ use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::LOCAL_CRATE;
use rustc_incremental::DepGraphFuture; use rustc_incremental::DepGraphFuture;
use rustc_lint::LintStore; use rustc_lint::LintStore;
@ -121,10 +120,8 @@ impl<'tcx> Queries<'tcx> {
pub fn parse(&self) -> Result<&Query<ast::Crate>> { pub fn parse(&self) -> Result<&Query<ast::Crate>> {
self.parse.compute(|| { self.parse.compute(|| {
passes::parse(self.session(), &self.compiler.input).map_err(|mut parse_error| { passes::parse(self.session(), &self.compiler.input)
parse_error.emit(); .map_err(|mut parse_error| parse_error.emit())
ErrorGuaranteed
})
}) })
} }

View file

@ -157,7 +157,7 @@ impl BoxPointers {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
if leaf_ty.is_box() { if leaf_ty.is_box() {
cx.struct_span_lint(BOX_POINTERS, span, |lint| { cx.struct_span_lint(BOX_POINTERS, span, |lint| {
lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit() lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit();
}); });
} }
} }
@ -318,7 +318,7 @@ impl UnsafeCode {
&self, &self,
cx: &EarlyContext<'_>, cx: &EarlyContext<'_>,
span: Span, span: Span,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
// This comes from a macro that has `#[allow_internal_unsafe]`. // This comes from a macro that has `#[allow_internal_unsafe]`.
if span.allows_unsafe() { if span.allows_unsafe() {
@ -350,7 +350,7 @@ impl EarlyLintPass for UnsafeCode {
macros using unsafe without triggering \ macros using unsafe without triggering \
the `unsafe_code` lint at their call site", the `unsafe_code` lint at their call site",
) )
.emit() .emit();
}); });
} }
} }
@ -360,7 +360,7 @@ impl EarlyLintPass for UnsafeCode {
// Don't warn about generated blocks; that'll just pollute the output. // Don't warn about generated blocks; that'll just pollute the output.
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) { if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
self.report_unsafe(cx, blk.span, |lint| { self.report_unsafe(cx, blk.span, |lint| {
lint.build("usage of an `unsafe` block").emit() lint.build("usage of an `unsafe` block").emit();
}); });
} }
} }
@ -370,12 +370,12 @@ impl EarlyLintPass for UnsafeCode {
match it.kind { match it.kind {
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
.report_unsafe(cx, it.span, |lint| { .report_unsafe(cx, it.span, |lint| {
lint.build("declaration of an `unsafe` trait").emit() lint.build("declaration of an `unsafe` trait").emit();
}), }),
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
.report_unsafe(cx, it.span, |lint| { .report_unsafe(cx, it.span, |lint| {
lint.build("implementation of an `unsafe` trait").emit() lint.build("implementation of an `unsafe` trait").emit();
}), }),
ast::ItemKind::Fn(..) => { ast::ItemKind::Fn(..) => {
@ -450,7 +450,9 @@ impl EarlyLintPass for UnsafeCode {
FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method", FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
FnCtxt::Assoc(_) => "implementation of an `unsafe` method", FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
}; };
self.report_unsafe(cx, span, |lint| lint.build(msg).emit()); self.report_unsafe(cx, span, |lint| {
lint.build(msg).emit();
});
} }
} }
} }
@ -559,7 +561,7 @@ impl MissingDoc {
MISSING_DOCS, MISSING_DOCS,
cx.tcx.sess.source_map().guess_head_span(sp), cx.tcx.sess.source_map().guess_head_span(sp),
|lint| { |lint| {
lint.build(&format!("missing documentation for {} {}", article, desc)).emit() lint.build(&format!("missing documentation for {} {}", article, desc)).emit();
}, },
); );
} }
@ -777,7 +779,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
"type could implement `Copy`; consider adding `impl \ "type could implement `Copy`; consider adding `impl \
Copy`", Copy`",
) )
.emit() .emit();
}) })
} }
} }
@ -858,7 +860,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
or a manual implementation", or a manual implementation",
cx.tcx.def_path_str(debug) cx.tcx.def_path_str(debug)
)) ))
.emit() .emit();
}); });
} }
} }
@ -1278,7 +1280,9 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
let msg = "transmuting &T to &mut T is undefined behavior, \ let msg = "transmuting &T to &mut T is undefined behavior, \
even if the reference is unused, consider instead using an UnsafeCell"; even if the reference is unused, consider instead using an UnsafeCell";
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit()); cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
lint.build(msg).emit();
});
} }
} }
@ -1328,7 +1332,7 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
if let Some(items) = attr.meta_item_list() { if let Some(items) = attr.meta_item_list() {
for item in items { for item in items {
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| { cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
lint.build("unstable feature").emit() lint.build("unstable feature").emit();
}); });
} }
} }
@ -1680,7 +1684,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
or lifetime parameters", or lifetime parameters",
predicate_kind_name, predicate predicate_kind_name, predicate
)) ))
.emit() .emit();
}); });
} }
} }
@ -1915,7 +1919,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
let attrs = cx.tcx.hir().attrs(it.hir_id()); let attrs = cx.tcx.hir().attrs(it.hir_id());
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) { if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| { cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
lint.build("cannot test inner items").emit() lint.build("cannot test inner items").emit();
}); });
} }
} }
@ -2040,7 +2044,7 @@ impl KeywordIdents {
format!("r#{}", ident), format!("r#{}", ident),
Applicability::MachineApplicable, Applicability::MachineApplicable,
) )
.emit() .emit();
}); });
} }
} }
@ -3055,7 +3059,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
"this signature doesn't match the previous declaration", "this signature doesn't match the previous declaration",
) )
.note_expected_found(&"", expected_str, &"", found_str) .note_expected_found(&"", expected_str, &"", found_str)
.emit() .emit();
}, },
); );
} }

View file

@ -593,7 +593,7 @@ pub trait LintContext: Sized {
&self, &self,
lint: &'static Lint, lint: &'static Lint,
span: Option<impl Into<MultiSpan>>, span: Option<impl Into<MultiSpan>>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
diagnostic: BuiltinLintDiagnostics, diagnostic: BuiltinLintDiagnostics,
) { ) {
self.lookup(lint, span, |lint| { self.lookup(lint, span, |lint| {
@ -840,19 +840,23 @@ pub trait LintContext: Sized {
&self, &self,
lint: &'static Lint, lint: &'static Lint,
span: Option<S>, span: Option<S>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
); );
fn struct_span_lint<S: Into<MultiSpan>>( fn struct_span_lint<S: Into<MultiSpan>>(
&self, &self,
lint: &'static Lint, lint: &'static Lint,
span: S, span: S,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
self.lookup(lint, Some(span), decorate); self.lookup(lint, Some(span), decorate);
} }
/// Emit a lint at the appropriate level, with no associated span. /// Emit a lint at the appropriate level, with no associated span.
fn lint(&self, lint: &'static Lint, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { fn lint(
&self,
lint: &'static Lint,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) {
self.lookup(lint, None as Option<Span>, decorate); self.lookup(lint, None as Option<Span>, decorate);
} }
} }
@ -893,7 +897,7 @@ impl LintContext for LateContext<'_> {
&self, &self,
lint: &'static Lint, lint: &'static Lint,
span: Option<S>, span: Option<S>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
let hir_id = self.last_node_with_lint_attrs; let hir_id = self.last_node_with_lint_attrs;
@ -920,7 +924,7 @@ impl LintContext for EarlyContext<'_> {
&self, &self,
lint: &'static Lint, lint: &'static Lint,
span: Option<S>, span: Option<S>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
self.builder.struct_lint(lint, span.map(|s| s.into()), decorate) self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
} }

View file

@ -45,7 +45,9 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
self.context.lookup_with_diagnostics( self.context.lookup_with_diagnostics(
lint_id.lint, lint_id.lint,
Some(span), Some(span),
|lint| lint.build(&msg).emit(), |lint| {
lint.build(&msg).emit();
},
diagnostic, diagnostic,
); );
} }

View file

@ -652,7 +652,7 @@ impl<'s> LintLevelsBuilder<'s> {
&self, &self,
lint: &'static Lint, lint: &'static Lint,
span: Option<MultiSpan>, span: Option<MultiSpan>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
let (level, src) = self.lint_level(lint); let (level, src) = self.lint_level(lint);
struct_lint_level(self.sess, lint, level, src, span, decorate) struct_lint_level(self.sess, lint, level, src, span, decorate)

View file

@ -180,13 +180,13 @@ impl EarlyLintPass for NonAsciiIdents {
} }
has_non_ascii_idents = true; has_non_ascii_idents = true;
cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| { cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
lint.build("identifier contains non-ASCII characters").emit() lint.build("identifier contains non-ASCII characters").emit();
}); });
if check_uncommon_codepoints if check_uncommon_codepoints
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed) && !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
{ {
cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| { cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
lint.build("identifier contains uncommon Unicode codepoints").emit() lint.build("identifier contains uncommon Unicode codepoints").emit();
}) })
} }
} }
@ -337,7 +337,7 @@ impl EarlyLintPass for NonAsciiIdents {
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32); let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
note += &char_info; note += &char_info;
} }
lint.build(&message).note(&note).note("please recheck to make sure their usages are indeed what you want").emit() lint.build(&message).note(&note).note("please recheck to make sure their usages are indeed what you want").emit();
}); });
} }
} }

View file

@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
let method = &call.ident.name; let method = &call.ident.name;
let message = let message =
format!("call to `.{}()` on a reference in this situation does nothing", &method,); format!("call to `.{}()` on a reference in this situation does nothing", &method,);
lint.build(&message).span_label(span, "unnecessary method call").note(&note).emit() lint.build(&message).span_label(span, "unnecessary method call").note(&note).emit();
}); });
} }
} }

View file

@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
predicate, predicate,
cx.tcx.def_path_str(needs_drop) cx.tcx.def_path_str(needs_drop)
); );
lint.build(&msg).emit() lint.build(&msg).emit();
}); });
} }
} }
@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
instead using `{}` to detect whether a type is trivially dropped", instead using `{}` to detect whether a type is trivially dropped",
cx.tcx.def_path_str(needs_drop) cx.tcx.def_path_str(needs_drop)
); );
lint.build(&msg).emit() lint.build(&msg).emit();
}); });
} }
} }

View file

@ -441,7 +441,7 @@ fn lint_uint_literal<'tcx>(
min, min,
max, max,
)) ))
.emit() .emit();
}); });
} }
} }
@ -502,7 +502,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
hir::ExprKind::Binary(binop, ref l, ref r) => { hir::ExprKind::Binary(binop, ref l, ref r) => {
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| { cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
lint.build("comparison is useless due to type limits").emit() lint.build("comparison is useless due to type limits").emit();
}); });
} }
} }
@ -1382,7 +1382,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
larger ({} bytes) than the next largest", larger ({} bytes) than the next largest",
largest largest
)) ))
.emit() .emit();
}, },
); );
} }

View file

@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
if !(type_permits_lack_of_use || fn_warned || op_warned) { if !(type_permits_lack_of_use || fn_warned || op_warned) {
cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| { cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
lint.build(&format!("unused result of type `{}`", ty)).emit() lint.build(&format!("unused result of type `{}`", ty)).emit();
}); });
} }
@ -368,9 +368,9 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
} else { } else {
lint.span_help(s.span, "use `drop` to clarify the intent"); lint.span_help(s.span, "use `drop` to clarify the intent");
} }
lint.emit() lint.emit();
} else { } else {
lint.build("path statement with no effect").emit() lint.build("path statement with no effect").emit();
} }
}); });
} }
@ -1111,7 +1111,7 @@ impl UnusedImportBraces {
}; };
cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| { cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
lint.build(&format!("braces around {} is unnecessary", node_name)).emit() lint.build(&format!("braces around {} is unnecessary", node_name)).emit();
}); });
} }
} }
@ -1170,7 +1170,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
"unnecessary allocation, use `&mut` instead" "unnecessary allocation, use `&mut` instead"
} }
}; };
lint.build(msg).emit() lint.build(msg).emit();
}); });
} }
} }

View file

@ -825,11 +825,13 @@ impl<'a> CrateLoader<'a> {
for (_, data) in self.cstore.iter_crate_data() { for (_, data) in self.cstore.iter_crate_data() {
if data.has_global_allocator() { if data.has_global_allocator() {
match global_allocator { match global_allocator {
Some(other_crate) => self.sess.err(&format!( Some(other_crate) => {
self.sess.err(&format!(
"the `#[global_allocator]` in {} conflicts with global allocator in: {}", "the `#[global_allocator]` in {} conflicts with global allocator in: {}",
other_crate, other_crate,
data.name() data.name()
)), ));
}
None => global_allocator = Some(data.name()), None => global_allocator = Some(data.name()),
} }
} }
@ -864,7 +866,7 @@ impl<'a> CrateLoader<'a> {
// don't perform this validation if the session has errors, as one of // don't perform this validation if the session has errors, as one of
// those errors may indicate a circular dependency which could cause // those errors may indicate a circular dependency which could cause
// this to stack overflow. // this to stack overflow.
if self.sess.has_errors() { if self.sess.has_errors().is_some() {
return; return;
} }

View file

@ -145,41 +145,49 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
("bundle", NativeLibKind::Static { bundle, .. }) => { ("bundle", NativeLibKind::Static { bundle, .. }) => {
*bundle = Some(value); *bundle = Some(value);
} }
("bundle", _) => sess.span_err( ("bundle", _) => {
sess.span_err(
span, span,
"bundle linking modifier is only compatible with \ "bundle linking modifier is only compatible with \
`static` linking kind", `static` linking kind",
), );
}
("verbatim", _) => lib.verbatim = Some(value), ("verbatim", _) => lib.verbatim = Some(value),
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
*whole_archive = Some(value); *whole_archive = Some(value);
} }
("whole-archive", _) => sess.span_err( ("whole-archive", _) => {
sess.span_err(
span, span,
"whole-archive linking modifier is only compatible with \ "whole-archive linking modifier is only compatible with \
`static` linking kind", `static` linking kind",
), );
}
("as-needed", NativeLibKind::Dylib { as_needed }) ("as-needed", NativeLibKind::Dylib { as_needed })
| ("as-needed", NativeLibKind::Framework { as_needed }) => { | ("as-needed", NativeLibKind::Framework { as_needed }) => {
*as_needed = Some(value); *as_needed = Some(value);
} }
("as-needed", _) => sess.span_err( ("as-needed", _) => {
sess.span_err(
span, span,
"as-needed linking modifier is only compatible with \ "as-needed linking modifier is only compatible with \
`dylib` and `framework` linking kinds", `dylib` and `framework` linking kinds",
), );
}
_ => sess.span_err( _ => {
sess.span_err(
span, span,
&format!( &format!(
"unrecognized linking modifier `{}`, expected one \ "unrecognized linking modifier `{}`, expected one \
of: bundle, verbatim, whole-archive, as-needed", of: bundle, verbatim, whole-archive, as-needed",
modifier modifier
), ),
), );
}
} }
} }
} else { } else {
@ -247,7 +255,9 @@ impl Collector<'_> {
Some(span) => { Some(span) => {
struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit(); struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit();
} }
None => self.tcx.sess.err(msg), None => {
self.tcx.sess.err(msg);
}
} }
} }
if lib.cfg.is_some() && !self.tcx.features().link_cfg { if lib.cfg.is_some() && !self.tcx.features().link_cfg {

View file

@ -2,7 +2,9 @@ use std::cmp;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId}; use rustc_errors::{
Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed,
};
use rustc_hir::HirId; use rustc_hir::HirId;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
@ -220,22 +222,28 @@ impl LintExpectation {
} }
} }
pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a, ()>); pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
impl<'a> LintDiagnosticBuilder<'a> { impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
/// Return the inner DiagnosticBuilder, first setting the primary message to `msg`. /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, ()> { pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, G> {
self.0.set_primary_message(msg); self.0.set_primary_message(msg);
self.0.set_is_lint(); self.0.set_is_lint();
self.0 self.0
} }
/// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder. /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
pub fn new(err: DiagnosticBuilder<'a, ()>) -> LintDiagnosticBuilder<'a> { pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
LintDiagnosticBuilder(err) LintDiagnosticBuilder(err)
} }
} }
impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
LintDiagnosticBuilder(self.0.forget_guarantee())
}
}
pub fn explain_lint_level_source( pub fn explain_lint_level_source(
sess: &Session, sess: &Session,
lint: &'static Lint, lint: &'static Lint,
@ -316,7 +324,7 @@ pub fn struct_lint_level<'s, 'd>(
level: Level, level: Level,
src: LintLevelSource, src: LintLevelSource,
span: Option<MultiSpan>, span: Option<MultiSpan>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + 'd, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) + 'd,
) { ) {
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
// the "real" work. // the "real" work.
@ -326,7 +334,7 @@ pub fn struct_lint_level<'s, 'd>(
level: Level, level: Level,
src: LintLevelSource, src: LintLevelSource,
span: Option<MultiSpan>, span: Option<MultiSpan>,
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>, decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) + 'd>,
) { ) {
// Check for future incompatibility lints and issue a stronger warning. // Check for future incompatibility lints and issue a stronger warning.
let future_incompatible = lint.future_incompatible; let future_incompatible = lint.future_incompatible;

View file

@ -258,7 +258,7 @@ fn late_report_deprecation(
let kind = tcx.def_kind(def_id).descr(def_id); let kind = tcx.def_kind(def_id).descr(def_id);
deprecation_suggestion(&mut diag, kind, suggestion, method_span); deprecation_suggestion(&mut diag, kind, suggestion, method_span);
} }
diag.emit() diag.emit();
}); });
} }
@ -483,7 +483,7 @@ impl<'tcx> TyCtxt<'tcx> {
) { ) {
let soft_handler = |lint, span, msg: &_| { let soft_handler = |lint, span, msg: &_| {
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| { self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
lint.build(msg).emit() lint.build(msg).emit();
}) })
}; };
match self.eval_stability(def_id, id, span, method_span) { match self.eval_stability(def_id, id, span, method_span) {

View file

@ -91,7 +91,7 @@ fn print_backtrace(backtrace: &Backtrace) {
impl From<ErrorHandled> for InterpErrorInfo<'_> { impl From<ErrorHandled> for InterpErrorInfo<'_> {
fn from(err: ErrorHandled) -> Self { fn from(err: ErrorHandled) -> Self {
match err { match err {
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => { ErrorHandled::Reported(ErrorGuaranteed { .. }) | ErrorHandled::Linted => {
err_inval!(ReferencedConstant) err_inval!(ReferencedConstant)
} }
ErrorHandled::TooGeneric => err_inval!(TooGeneric), ErrorHandled::TooGeneric => err_inval!(TooGeneric),
@ -160,7 +160,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
match self { match self {
TooGeneric => write!(f, "encountered overly generic constant"), TooGeneric => write!(f, "encountered overly generic constant"),
ReferencedConstant => write!(f, "referenced constant has errors"), ReferencedConstant => write!(f, "referenced constant has errors"),
AlreadyReported(ErrorGuaranteed) => { AlreadyReported(ErrorGuaranteed { .. }) => {
write!(f, "encountered constants with type errors, stopping evaluation") write!(f, "encountered constants with type errors, stopping evaluation")
} }
Layout(ref err) => write!(f, "{}", err), Layout(ref err) => write!(f, "{}", err),

View file

@ -252,7 +252,9 @@ rustc_queries! {
} }
/// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`. /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
query thir_body(key: ty::WithOptConstParam<LocalDefId>) -> (&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId) { query thir_body(key: ty::WithOptConstParam<LocalDefId>)
-> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed>
{
// Perf tests revealed that hashing THIR is inefficient (see #85729). // Perf tests revealed that hashing THIR is inefficient (see #85729).
no_hash no_hash
desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) } desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }

View file

@ -31,12 +31,12 @@ pub struct Graph {
pub children: DefIdMap<Children>, pub children: DefIdMap<Children>,
/// Whether an error was emitted while constructing the graph. /// Whether an error was emitted while constructing the graph.
pub has_errored: bool, pub has_errored: Option<ErrorGuaranteed>,
} }
impl Graph { impl Graph {
pub fn new() -> Graph { pub fn new() -> Graph {
Graph { parent: Default::default(), children: Default::default(), has_errored: false } Graph { parent: Default::default(), children: Default::default(), has_errored: None }
} }
/// The parent of a given impl, which is the `DefId` of the trait when the /// The parent of a given impl, which is the `DefId` of the trait when the
@ -246,8 +246,10 @@ pub fn ancestors<'tcx>(
) -> Result<Ancestors<'tcx>, ErrorGuaranteed> { ) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
let specialization_graph = tcx.specialization_graph_of(trait_def_id); let specialization_graph = tcx.specialization_graph_of(trait_def_id);
if specialization_graph.has_errored || tcx.type_of(start_from_impl).references_error() { if let Some(reported) = specialization_graph.has_errored {
Err(ErrorGuaranteed) Err(reported)
} else if let Some(reported) = tcx.type_of(start_from_impl).error_reported() {
Err(reported)
} else { } else {
Ok(Ancestors { Ok(Ancestors {
trait_def_id, trait_def_id,

View file

@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::HashingControls; use rustc_data_structures::stable_hasher::HashingControls;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -453,7 +452,7 @@ impl<'tcx> AdtDef<'tcx> {
} }
Err(err) => { Err(err) => {
let msg = match err { let msg = match err {
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => { ErrorHandled::Reported(_) | ErrorHandled::Linted => {
"enum discriminant evaluation failed" "enum discriminant evaluation failed"
} }
ErrorHandled::TooGeneric => "enum discriminant depends on generics", ErrorHandled::TooGeneric => "enum discriminant depends on generics",

View file

@ -264,7 +264,7 @@ impl<'tcx> Const<'tcx> {
if let Some(val) = self.val().try_eval(tcx, param_env) { if let Some(val) = self.val().try_eval(tcx, param_env) {
match val { match val {
Ok(val) => Const::from_value(tcx, val, self.ty()), Ok(val) => Const::from_value(tcx, val, self.ty()),
Err(ErrorGuaranteed) => tcx.const_error(self.ty()), Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
} }
} else { } else {
self self

View file

@ -91,7 +91,10 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// except through the error-reporting functions on a [`tcx`][TyCtxt]. /// except through the error-reporting functions on a [`tcx`][TyCtxt].
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[derive(TyEncodable, TyDecodable, HashStable)] #[derive(TyEncodable, TyDecodable, HashStable)]
pub struct DelaySpanBugEmitted(()); pub struct DelaySpanBugEmitted {
pub reported: ErrorGuaranteed,
_priv: (),
}
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>; type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
@ -1236,8 +1239,8 @@ impl<'tcx> TyCtxt<'tcx> {
/// ensure it gets used. /// ensure it gets used.
#[track_caller] #[track_caller]
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> { pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
self.sess.delay_span_bug(span, msg); let reported = self.sess.delay_span_bug(span, msg);
self.mk_ty(Error(DelaySpanBugEmitted(()))) self.mk_ty(Error(DelaySpanBugEmitted { reported, _priv: () }))
} }
/// Like [TyCtxt::ty_error] but for constants. /// Like [TyCtxt::ty_error] but for constants.
@ -1258,8 +1261,11 @@ impl<'tcx> TyCtxt<'tcx> {
span: S, span: S,
msg: &str, msg: &str,
) -> Const<'tcx> { ) -> Const<'tcx> {
self.sess.delay_span_bug(span, msg); let reported = self.sess.delay_span_bug(span, msg);
self.mk_const(ty::ConstS { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty }) self.mk_const(ty::ConstS {
val: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }),
ty,
})
} }
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool { pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
@ -2733,7 +2739,7 @@ impl<'tcx> TyCtxt<'tcx> {
lint: &'static Lint, lint: &'static Lint,
hir_id: HirId, hir_id: HirId,
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
let (level, src) = self.lint_level_at_node(lint, hir_id); let (level, src) = self.lint_level_at_node(lint, hir_id);
struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate); struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
@ -2743,7 +2749,7 @@ impl<'tcx> TyCtxt<'tcx> {
self, self,
lint: &'static Lint, lint: &'static Lint,
id: HirId, id: HirId,
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
) { ) {
let (level, src) = self.lint_level_at_node(lint, id); let (level, src) = self.lint_level_at_node(lint, id);
struct_lint_level(self.sess, lint, level, src, None, decorate); struct_lint_level(self.sess, lint, level, src, None, decorate);

View file

@ -51,6 +51,7 @@
//! ``` //! ```
use crate::mir; use crate::mir;
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
@ -151,6 +152,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
fn references_error(&self) -> bool { fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR) self.has_type_flags(TypeFlags::HAS_ERROR)
} }
fn error_reported(&self) -> Option<ErrorGuaranteed> {
if self.references_error() {
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else {
None
}
}
fn has_param_types_or_consts(&self) -> bool { fn has_param_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
} }

View file

@ -118,7 +118,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
}; };
let body = tcx.hir().body(body_id); let body = tcx.hir().body(body_id);
let (thir, expr) = tcx.thir_body(def); let (thir, expr) = tcx
.thir_body(def)
.unwrap_or_else(|_| (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)));
// We ran all queries that depended on THIR at the beginning // We ran all queries that depended on THIR at the beginning
// of `mir_build`, so now we can steal it // of `mir_build`, so now we can steal it
let thir = thir.steal(); let thir = thir.steal();
@ -229,7 +231,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
let return_ty = typeck_results.node_type(id); let return_ty = typeck_results.node_type(id);
let (thir, expr) = tcx.thir_body(def); let (thir, expr) = tcx
.thir_body(def)
.unwrap_or_else(|_| (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)));
// We ran all queries that depended on THIR at the beginning // We ran all queries that depended on THIR at the beginning
// of `mir_build`, so now we can steal it // of `mir_build`, so now we can steal it
let thir = thir.steal(); let thir = thir.steal();

View file

@ -405,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
} else { } else {
ty::WithOptConstParam::unknown(closure_id) ty::WithOptConstParam::unknown(closure_id)
}; };
let (closure_thir, expr) = self.tcx.thir_body(closure_def); let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
(self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
});
let closure_thir = &closure_thir.borrow(); let closure_thir = &closure_thir.borrow();
let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id); let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
let mut closure_visitor = let mut closure_visitor =
@ -606,7 +608,10 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
return; return;
} }
let (thir, expr) = tcx.thir_body(def); let (thir, expr) = match tcx.thir_body(def) {
Ok(body) => body,
Err(_) => return,
};
let thir = &thir.borrow(); let thir = &thir.borrow();
// If `thir` is empty, a type error occurred, skip this body. // If `thir` is empty, a type error occurred, skip this body.
if thir.exprs.is_empty() { if thir.exprs.is_empty() {

View file

@ -7,6 +7,7 @@ use crate::thir::util::UserAnnotatedTyHelpers;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::HirId; use rustc_hir::HirId;
@ -20,22 +21,25 @@ use rustc_span::Span;
crate fn thir_body<'tcx>( crate fn thir_body<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
owner_def: ty::WithOptConstParam<LocalDefId>, owner_def: ty::WithOptConstParam<LocalDefId>,
) -> (&'tcx Steal<Thir<'tcx>>, ExprId) { ) -> Result<(&'tcx Steal<Thir<'tcx>>, ExprId), ErrorGuaranteed> {
let hir = tcx.hir(); let hir = tcx.hir();
let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did))); let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did)));
let mut cx = Cx::new(tcx, owner_def); let mut cx = Cx::new(tcx, owner_def);
if cx.typeck_results.tainted_by_errors.is_some() { if let Some(reported) = cx.typeck_results.tainted_by_errors {
return (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)); return Err(reported);
} }
let expr = cx.mirror_expr(&body.value); let expr = cx.mirror_expr(&body.value);
(tcx.alloc_steal_thir(cx.thir), expr) Ok((tcx.alloc_steal_thir(cx.thir), expr))
} }
crate fn thir_tree<'tcx>( crate fn thir_tree<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
owner_def: ty::WithOptConstParam<LocalDefId>, owner_def: ty::WithOptConstParam<LocalDefId>,
) -> String { ) -> String {
format!("{:#?}", thir_body(tcx, owner_def).0.steal()) match thir_body(tcx, owner_def) {
Ok((thir, _)) => format!("{:#?}", thir.steal()),
Err(_) => "error".into(),
}
} }
struct Cx<'tcx> { struct Cx<'tcx> {

View file

@ -194,7 +194,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::INDIRECT_STRUCTURAL_MATCH, lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id, self.id,
self.span, self.span,
|lint| lint.build(&msg).emit(), |lint| {
lint.build(&msg).emit();
},
); );
} else { } else {
debug!( debug!(
@ -272,7 +274,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id, id,
span, span,
|lint| lint.build("floating-point types cannot be used in patterns").emit(), |lint| {
lint.build("floating-point types cannot be used in patterns").emit();
},
); );
} }
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
@ -284,7 +288,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
if self.include_lint_checks { if self.include_lint_checks {
tcx.sess.span_err(span, msg); tcx.sess.span_err(span, msg);
} else { } else {
tcx.sess.delay_span_bug(span, msg) tcx.sess.delay_span_bug(span, msg);
} }
PatKind::Wild PatKind::Wild
} }
@ -301,7 +305,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
if self.include_lint_checks { if self.include_lint_checks {
tcx.sess.span_err(self.span, &msg); tcx.sess.span_err(self.span, &msg);
} else { } else {
tcx.sess.delay_span_bug(self.span, &msg) tcx.sess.delay_span_bug(self.span, &msg);
} }
PatKind::Wild PatKind::Wild
} }
@ -331,7 +335,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
cv.ty(), cv.ty(),
cv.ty(), cv.ty(),
); );
lint.build(&msg).emit() lint.build(&msg).emit();
}, },
); );
} }
@ -356,7 +360,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
if self.include_lint_checks { if self.include_lint_checks {
tcx.sess.span_err(span, &msg); tcx.sess.span_err(span, &msg);
} else { } else {
tcx.sess.delay_span_bug(span, &msg) tcx.sess.delay_span_bug(span, &msg);
} }
PatKind::Wild PatKind::Wild
} }
@ -393,7 +397,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
if self.include_lint_checks { if self.include_lint_checks {
tcx.sess.span_err(span, &msg); tcx.sess.span_err(span, &msg);
} else { } else {
tcx.sess.delay_span_bug(span, &msg) tcx.sess.delay_span_bug(span, &msg);
} }
PatKind::Wild PatKind::Wild
} }
@ -471,7 +475,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::INDIRECT_STRUCTURAL_MATCH, lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id, self.id,
self.span, self.span,
|lint| lint.build(&msg).emit(), |lint| {lint.build(&msg).emit();},
); );
} }
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
@ -482,7 +486,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
if self.include_lint_checks { if self.include_lint_checks {
tcx.sess.span_err(span, &msg); tcx.sess.span_err(span, &msg);
} else { } else {
tcx.sess.delay_span_bug(span, &msg) tcx.sess.delay_span_bug(span, &msg);
} }
} }
PatKind::Wild PatKind::Wild
@ -539,7 +543,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::POINTER_STRUCTURAL_MATCH, lint::builtin::POINTER_STRUCTURAL_MATCH,
id, id,
span, span,
|lint| lint.build(&msg).emit(), |lint| {
lint.build(&msg).emit();
},
); );
} }
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
@ -550,7 +556,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
if self.include_lint_checks { if self.include_lint_checks {
tcx.sess.span_err(span, &msg); tcx.sess.span_err(span, &msg);
} else { } else {
tcx.sess.delay_span_bug(span, &msg) tcx.sess.delay_span_bug(span, &msg);
} }
PatKind::Wild PatKind::Wild
} }
@ -575,7 +581,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH, lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
id, id,
span, span,
|lint| lint.build(&msg).emit(), |lint| {
lint.build(&msg).emit();
},
); );
} }

View file

@ -64,7 +64,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
place: &Place<'tcx>, place: &Place<'tcx>,
const_item: DefId, const_item: DefId,
location: Location, location: Location,
decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b, ()>, decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) -> DiagnosticBuilder<'b, ()>,
) { ) {
// Don't lint on borrowing/assigning when a dereference is involved. // Don't lint on borrowing/assigning when a dereference is involved.
// If we 'leave' the temporary via a dereference, we must // If we 'leave' the temporary via a dereference, we must
@ -88,7 +88,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|lint| { |lint| {
decorate(lint) decorate(lint)
.span_note(self.tcx.def_span(const_item), "`const` item defined here") .span_note(self.tcx.def_span(const_item), "`const` item defined here")
.emit() .emit();
}, },
); );
} }

View file

@ -46,7 +46,7 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
does not derive Copy (error E0133)" does not derive Copy (error E0133)"
.to_string() .to_string()
}; };
lint.build(&message).emit() lint.build(&message).emit();
}); });
} }
@ -110,7 +110,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \ reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
(loads and stores via `*p` must be properly aligned even when using raw pointers)" (loads and stores via `*p` must be properly aligned even when using raw pointers)"
) )
.emit() .emit();
}, },
); );
} }

View file

@ -538,7 +538,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| { self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
let mut err = lint.build(message); let mut err = lint.build(message);
err.span_label(source_info.span, format!("{:?}", panic)); err.span_label(source_info.span, format!("{:?}", panic));
err.emit() err.emit();
}); });
} }
} }

View file

@ -180,7 +180,7 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
use rustc_errors::{ErrorGuaranteed, FatalError}; use rustc_errors::FatalError;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::itemlikevisit::ItemLikeVisitor;
@ -716,9 +716,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
match self.tcx.const_eval_resolve(param_env, ct, None) { match self.tcx.const_eval_resolve(param_env, ct, None) {
// The `monomorphize` call should have evaluated that constant already. // The `monomorphize` call should have evaluated that constant already.
Ok(val) => val, Ok(val) => val,
Err(ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted) => { Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
return;
}
Err(ErrorHandled::TooGeneric) => span_bug!( Err(ErrorHandled::TooGeneric) => span_bug!(
self.body.source_info(location).span, self.body.source_info(location).span,
"collection encountered polymorphic constant: {:?}", "collection encountered polymorphic constant: {:?}",
@ -750,7 +748,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
substituted_constant, substituted_constant,
val val
), ),
Err(ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted) => {} Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => {}
Err(ErrorHandled::TooGeneric) => span_bug!( Err(ErrorHandled::TooGeneric) => span_bug!(
self.body.source_info(location).span, self.body.source_info(location).span,
"collection encountered polymorphic constant: {}", "collection encountered polymorphic constant: {}",
@ -864,7 +862,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|lint| { |lint| {
let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes())); let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
err.span_label(source_info.span, "value moved from here"); err.span_label(source_info.span, "value moved from here");
err.emit() err.emit();
}, },
); );
} }

View file

@ -202,7 +202,7 @@ pub(crate) fn emit_unescape_error(
diag.emit(); diag.emit();
} }
EscapeError::TooShortHexEscape => { EscapeError::TooShortHexEscape => {
handler.span_err(span, "numeric character escape is too short") handler.span_err(span, "numeric character escape is too short");
} }
EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
let (c, span) = last_char(); let (c, span) = last_char();

View file

@ -212,10 +212,10 @@ impl<'a> Parser<'a> {
if let Err(mut e) = self.expect_semi() { if let Err(mut e) = self.expect_semi() {
match tree.kind { match tree.kind {
UseTreeKind::Glob => { UseTreeKind::Glob => {
e.note("the wildcard token must be last on the path").emit(); e.note("the wildcard token must be last on the path");
} }
UseTreeKind::Nested(..) => { UseTreeKind::Nested(..) => {
e.note("glob-like brace syntax must be last on the path").emit(); e.note("glob-like brace syntax must be last on the path");
} }
_ => (), _ => (),
} }
@ -1485,7 +1485,7 @@ impl<'a> Parser<'a> {
// Make sure an error was emitted (either by recovering an angle bracket, // Make sure an error was emitted (either by recovering an angle bracket,
// or by finding an identifier as the next token), since we're // or by finding an identifier as the next token), since we're
// going to continue parsing // going to continue parsing
assert!(self.sess.span_diagnostic.has_errors()); assert!(self.sess.span_diagnostic.has_errors().is_some());
} else { } else {
return Err(err); return Err(err);
} }

View file

@ -169,7 +169,7 @@ impl CheckAttrVisitor<'_> {
} }
ast::AttrStyle::Inner => "crate-level attribute should be in the root module", ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
}; };
lint.build(msg).emit() lint.build(msg).emit();
}); });
} }
} }
@ -236,7 +236,7 @@ impl CheckAttrVisitor<'_> {
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build("`#[inline]` is ignored on function prototypes").emit() lint.build("`#[inline]` is ignored on function prototypes").emit();
}); });
true true
} }

View file

@ -1588,7 +1588,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
shorthands, shorthands,
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
err.emit() err.emit();
}, },
); );
} else { } else {
@ -1611,7 +1611,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
non_shorthands, non_shorthands,
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
err.emit() err.emit();
}, },
); );
} }

View file

@ -128,7 +128,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
String::new(), String::new(),
rustc_errors::Applicability::MachineApplicable, rustc_errors::Applicability::MachineApplicable,
) )
.emit() .emit();
}); });
} }
@ -728,10 +728,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
INEFFECTIVE_UNSTABLE_TRAIT_IMPL, INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(), item.hir_id(),
span, span,
|lint| lint |lint| {lint
.build("an `#[unstable]` annotation here has no effect") .build("an `#[unstable]` annotation here has no effect")
.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information") .note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
.emit() .emit();}
); );
} }
} }

View file

@ -1742,7 +1742,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
descr, descr,
self.tcx.crate_name(def_id.krate) self.tcx.crate_name(def_id.krate)
)) ))
.emit() .emit();
}, },
); );
} }
@ -1786,7 +1786,9 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
lint::builtin::PRIVATE_IN_PUBLIC, lint::builtin::PRIVATE_IN_PUBLIC,
hir_id, hir_id,
span, span,
|lint| lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(), |lint| {
lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
},
); );
} }
} }

View file

@ -1997,7 +1997,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
Vec::new(), Vec::new(),
&[], &[],
); );
db.emit() db.emit();
}, },
); );
} }

View file

@ -3143,10 +3143,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
for bound in lifetime_i.bounds { for bound in lifetime_i.bounds {
match bound { match bound {
hir::GenericBound::Outlives(ref lt) => match lt.name { hir::GenericBound::Outlives(ref lt) => match lt.name {
hir::LifetimeName::Underscore => self.tcx.sess.delay_span_bug( hir::LifetimeName::Underscore => {
self.tcx.sess.delay_span_bug(
lt.span, lt.span,
"use of `'_` in illegal place, but not caught by lowering", "use of `'_` in illegal place, but not caught by lowering",
), );
}
hir::LifetimeName::Static => { hir::LifetimeName::Static => {
self.insert_lifetime(lt, Region::Static); self.insert_lifetime(lt, Region::Static);
self.tcx self.tcx
@ -3172,7 +3174,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
lt.span, lt.span,
"lowering generated `ImplicitObjectLifetimeDefault` \ "lowering generated `ImplicitObjectLifetimeDefault` \
outside of an object type", outside of an object type",
) );
} }
hir::LifetimeName::Error => { hir::LifetimeName::Error => {
// No need to do anything, error already reported. // No need to do anything, error already reported.

View file

@ -100,7 +100,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
match sp { match sp {
Some(sp) => sess.span_err(sp, s), Some(sp) => sess.span_err(sp, s),
None => sess.err(s), None => sess.err(s),
} };
err_count += 1; err_count += 1;
}; };
if s.is_empty() { if s.is_empty() {

View file

@ -262,7 +262,7 @@ impl Session {
} }
diag.emit(); diag.emit();
// If we should err, make sure we did. // If we should err, make sure we did.
if must_err && !self.has_errors() { if must_err && !self.has_errors().is_some() {
// We have skipped a feature gate, and not run into other errors... reject. // We have skipped a feature gate, and not run into other errors... reject.
self.err( self.err(
"`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \ "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \
@ -404,13 +404,13 @@ impl Session {
self.span_err(sp, msg); self.span_err(sp, msg);
} }
} }
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed {
self.diagnostic().span_err(sp, msg) self.diagnostic().span_err(sp, msg)
} }
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) { pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
self.diagnostic().span_err_with_code(sp, &msg, code) self.diagnostic().span_err_with_code(sp, &msg, code)
} }
pub fn err(&self, msg: &str) { pub fn err(&self, msg: &str) -> ErrorGuaranteed {
self.diagnostic().err(msg) self.diagnostic().err(msg)
} }
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
@ -420,7 +420,7 @@ impl Session {
pub fn err_count(&self) -> usize { pub fn err_count(&self) -> usize {
self.diagnostic().err_count() self.diagnostic().err_count()
} }
pub fn has_errors(&self) -> bool { pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
self.diagnostic().has_errors() self.diagnostic().has_errors()
} }
pub fn has_errors_or_delayed_span_bugs(&self) -> bool { pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
@ -430,9 +430,9 @@ impl Session {
self.diagnostic().abort_if_errors(); self.diagnostic().abort_if_errors();
} }
pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
if self.diagnostic().has_errors_or_lint_errors() { if let Some(reported) = self.diagnostic().has_errors_or_lint_errors() {
self.diagnostic().emit_stashed_diagnostics(); let _ = self.diagnostic().emit_stashed_diagnostics();
Err(ErrorGuaranteed) Err(reported)
} else { } else {
Ok(()) Ok(())
} }
@ -444,7 +444,11 @@ impl Session {
{ {
let old_count = self.err_count(); let old_count = self.err_count();
let result = f(); let result = f();
if self.err_count() == old_count { Ok(result) } else { Err(ErrorGuaranteed) } if self.err_count() == old_count {
Ok(result)
} else {
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
}
} }
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.diagnostic().span_warn(sp, msg) self.diagnostic().span_warn(sp, msg)
@ -457,7 +461,7 @@ impl Session {
} }
/// Delay a span_bug() call until abort_if_errors() /// Delay a span_bug() call until abort_if_errors()
#[track_caller] #[track_caller]
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed {
self.diagnostic().delay_span_bug(sp, msg) self.diagnostic().delay_span_bug(sp, msg)
} }
@ -1387,12 +1391,18 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers; let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
match unsupported_sanitizers.into_iter().count() { match unsupported_sanitizers.into_iter().count() {
0 => {} 0 => {}
1 => sess 1 => {
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)), sess.err(&format!(
_ => sess.err(&format!( "{} sanitizer is not supported for this target",
unsupported_sanitizers
));
}
_ => {
sess.err(&format!(
"{} sanitizers are not supported for this target", "{} sanitizers are not supported for this target",
unsupported_sanitizers unsupported_sanitizers
)), ));
}
} }
// Cannot mix and match sanitizers. // Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter(); let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
@ -1446,7 +1456,7 @@ pub enum IncrCompSession {
InvalidBecauseOfErrors { session_directory: PathBuf }, InvalidBecauseOfErrors { session_directory: PathBuf },
} }
pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) { pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
let emitter: Box<dyn Emitter + sync::Send> = match output { let emitter: Box<dyn Emitter + sync::Send> = match output {
config::ErrorOutputType::HumanReadable(kind) => { config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip(); let (short, color_config) = kind.unzip();
@ -1457,7 +1467,8 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) {
} }
}; };
let handler = rustc_errors::Handler::with_emitter(true, None, emitter); let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
handler.struct_fatal(msg).emit(); let reported = handler.struct_fatal(msg).emit();
reported
} }
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {

View file

@ -51,7 +51,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
// leading to an ambiguous result. So report this as an // leading to an ambiguous result. So report this as an
// overflow bug, since I believe this is the only case // overflow bug, since I believe this is the only case
// where ambiguity can result. // where ambiguity can result.
infcx.tcx.sess.delay_span_bug( let reported = infcx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP, rustc_span::DUMMY_SP,
&format!( &format!(
"encountered ambiguity selecting `{:?}` during codegen, presuming due to \ "encountered ambiguity selecting `{:?}` during codegen, presuming due to \
@ -59,21 +59,21 @@ pub fn codegen_fulfill_obligation<'tcx>(
trait_ref trait_ref
), ),
); );
return Err(ErrorGuaranteed); return Err(reported);
} }
Err(Unimplemented) => { Err(Unimplemented) => {
// This can trigger when we probe for the source of a `'static` lifetime requirement // This can trigger when we probe for the source of a `'static` lifetime requirement
// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound. // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
// This can also trigger when we have a global bound that is not actually satisfied, // This can also trigger when we have a global bound that is not actually satisfied,
// but was included during typeck due to the trivial_bounds feature. // but was included during typeck due to the trivial_bounds feature.
infcx.tcx.sess.delay_span_bug( let guar = infcx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP, rustc_span::DUMMY_SP,
&format!( &format!(
"Encountered error `Unimplemented` selecting `{:?}` during codegen", "Encountered error `Unimplemented` selecting `{:?}` during codegen",
trait_ref trait_ref
), ),
); );
return Err(ErrorGuaranteed); return Err(guar);
} }
Err(e) => { Err(e) => {
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)

View file

@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir; use rustc_middle::thir;
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable}; use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, DelaySpanBugEmitted, TyCtxt, TypeFoldable};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::Span; use rustc_span::Span;
@ -177,8 +177,9 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
false => NotConstEvaluatable::MentionsParam, false => NotConstEvaluatable::MentionsParam,
}), }),
Err(ErrorHandled::Linted) => { Err(ErrorHandled::Linted) => {
let reported =
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
Err(NotConstEvaluatable::Error(ErrorGuaranteed)) Err(NotConstEvaluatable::Error(reported))
} }
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
Ok(_) => Ok(()), Ok(_) => Ok(()),
@ -244,7 +245,7 @@ impl<'tcx> AbstractConst<'tcx> {
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
match ct.val() { match ct.val() {
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()), ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
ty::ConstKind::Error(_) => Err(ErrorGuaranteed), ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
_ => Ok(None), _ => Ok(None),
} }
} }
@ -280,17 +281,19 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
} }
fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> { fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
self.tcx let reported = self
.tcx
.sess .sess
.struct_span_err(self.root_span(), "overly complex generic constant") .struct_span_err(self.root_span(), "overly complex generic constant")
.span_label(span, msg) .span_label(span, msg)
.help("consider moving this anonymous constant into a `const` function") .help("consider moving this anonymous constant into a `const` function")
.emit(); .emit();
Err(ErrorGuaranteed) Err(reported)
} }
fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> { fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
self.tcx let reported = self
.tcx
.sess .sess
.struct_span_err(self.root_span(), "overly complex generic constant") .struct_span_err(self.root_span(), "overly complex generic constant")
.span_label(span, msg) .span_label(span, msg)
@ -298,7 +301,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
.note("this operation may be supported in the future") .note("this operation may be supported in the future")
.emit(); .emit();
Err(ErrorGuaranteed) Err(reported)
} }
fn new( fn new(
@ -553,11 +556,7 @@ pub(super) fn thir_abstract_const<'tcx>(
_ => return Ok(None), _ => return Ok(None),
} }
let body = tcx.thir_body(def); let body = tcx.thir_body(def)?;
if body.0.borrow().exprs.is_empty() {
// type error in constant, there is no thir
return Err(ErrorGuaranteed);
}
AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))? AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
.map(AbstractConstBuilder::build) .map(AbstractConstBuilder::build)
@ -580,7 +579,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
Ok(false) Ok(false)
})() })()
.unwrap_or_else(|ErrorGuaranteed| true) .unwrap_or_else(|_: ErrorGuaranteed| true)
// FIXME(generic_const_exprs): We should instead have this // FIXME(generic_const_exprs): We should instead have this
// method return the resulting `ty::Const` and return `ConstKind::Error` // method return the resulting `ty::Const` and return `ConstKind::Error`
// on `ErrorGuaranteed`. // on `ErrorGuaranteed`.

View file

@ -63,7 +63,7 @@ pub trait InferCtxtExt<'tcx> {
errors: &[FulfillmentError<'tcx>], errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>, body_id: Option<hir::BodyId>,
fallback_has_occurred: bool, fallback_has_occurred: bool,
); ) -> ErrorGuaranteed;
fn report_overflow_error<T>( fn report_overflow_error<T>(
&self, &self,
@ -111,7 +111,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
errors: &[FulfillmentError<'tcx>], errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>, body_id: Option<hir::BodyId>,
fallback_has_occurred: bool, fallback_has_occurred: bool,
) { ) -> ErrorGuaranteed {
#[derive(Debug)] #[derive(Debug)]
struct ErrorDescriptor<'tcx> { struct ErrorDescriptor<'tcx> {
predicate: ty::Predicate<'tcx>, predicate: ty::Predicate<'tcx>,
@ -190,6 +190,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.report_fulfillment_error(error, body_id, fallback_has_occurred); self.report_fulfillment_error(error, body_id, fallback_has_occurred);
} }
} }
self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fullfillment errors")
} }
/// Reports that an overflow has occurred and halts compilation. We /// Reports that an overflow has occurred and halts compilation. We
@ -312,7 +314,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let predicate_is_const = ty::BoundConstness::ConstIfConst let predicate_is_const = ty::BoundConstness::ConstIfConst
== trait_predicate.skip_binder().constness; == trait_predicate.skip_binder().constness;
if self.tcx.sess.has_errors() && trait_predicate.references_error() { if self.tcx.sess.has_errors().is_some()
&& trait_predicate.references_error()
{
return; return;
} }
let trait_ref = trait_predicate.to_poly_trait_ref(); let trait_ref = trait_predicate.to_poly_trait_ref();
@ -919,7 +923,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
// Already reported in the query. // Already reported in the query.
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorGuaranteed)) => { SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => {
// FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token. // FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token.
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error"); self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
return; return;
@ -1857,7 +1861,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
// Same hacky approach as above to avoid deluging user // Same hacky approach as above to avoid deluging user
// with error messages. // with error messages.
if arg.references_error() if arg.references_error()
|| self.tcx.sess.has_errors() || self.tcx.sess.has_errors().is_some()
|| self.is_tainted_by_errors() || self.is_tainted_by_errors()
{ {
return; return;
@ -1868,7 +1872,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
ty::PredicateKind::Subtype(data) => { ty::PredicateKind::Subtype(data) => {
if data.references_error() if data.references_error()
|| self.tcx.sess.has_errors() || self.tcx.sess.has_errors().is_some()
|| self.is_tainted_by_errors() || self.is_tainted_by_errors()
{ {
// no need to overload user in such cases // no need to overload user in such cases
@ -1910,7 +1914,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
} }
_ => { _ => {
if self.tcx.sess.has_errors() || self.is_tainted_by_errors() { if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() {
return; return;
} }
let mut err = struct_span_err!( let mut err = struct_span_err!(

View file

@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_errors::ErrorGuaranteed;
use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
@ -630,14 +629,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
), ),
} }
} }
(Err(ErrorHandled::Reported(ErrorGuaranteed)), _) (Err(ErrorHandled::Reported(reported)), _)
| (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => { | (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
ProcessResult::Error(CodeSelectionError( CodeSelectionError(SelectionError::NotConstEvaluatable(
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error( NotConstEvaluatable::Error(reported),
ErrorGuaranteed,
)), )),
)) ),
}
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
span_bug!( span_bug!(
obligation.cause.span(self.selcx.tcx()), obligation.cause.span(self.selcx.tcx()),

View file

@ -231,8 +231,8 @@ fn do_normalize_predicates<'tcx>(
match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) { match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
Ok(predicates) => predicates, Ok(predicates) => predicates,
Err(errors) => { Err(errors) => {
infcx.report_fulfillment_errors(&errors, None, false); let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorGuaranteed); return Err(reported);
} }
}; };
@ -258,13 +258,15 @@ fn do_normalize_predicates<'tcx>(
// represents a legitimate failure due to some kind of // represents a legitimate failure due to some kind of
// unconstrained variable, and it seems better not to ICE, // unconstrained variable, and it seems better not to ICE,
// all things considered. // all things considered.
tcx.sess.span_err(span, &fixup_err.to_string()); let reported = tcx.sess.span_err(span, &fixup_err.to_string());
return Err(ErrorGuaranteed); return Err(reported);
} }
}; };
if predicates.needs_infer() { if predicates.needs_infer() {
tcx.sess.delay_span_bug(span, "encountered inference variables after `fully_resolve`"); let reported = tcx
Err(ErrorGuaranteed) .sess
.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
Err(reported)
} else { } else {
Ok(predicates) Ok(predicates)
} }

View file

@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
use rustc_parse_format::{ParseMode, Parser, Piece, Position}; use rustc_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span; use rustc_span::{Span, DUMMY_SP};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct OnUnimplementedFormatString(Symbol); pub struct OnUnimplementedFormatString(Symbol);
@ -47,8 +47,7 @@ fn parse_error(
if let Some(note) = note { if let Some(note) = note {
diag.note(note); diag.note(note);
} }
diag.emit(); diag.emit()
ErrorGuaranteed
} }
impl<'tcx> OnUnimplementedDirective { impl<'tcx> OnUnimplementedDirective {
@ -59,7 +58,7 @@ impl<'tcx> OnUnimplementedDirective {
span: Span, span: Span,
is_root: bool, is_root: bool,
) -> Result<Self, ErrorGuaranteed> { ) -> Result<Self, ErrorGuaranteed> {
let mut errored = false; let mut errored = None;
let mut item_iter = items.iter(); let mut item_iter = items.iter();
let parse_value = |value_str| { let parse_value = |value_str| {
@ -91,8 +90,8 @@ impl<'tcx> OnUnimplementedDirective {
) )
})?; })?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| { attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() { if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
errored = true; errored = Some(guar);
} }
true true
}); });
@ -134,13 +133,10 @@ impl<'tcx> OnUnimplementedDirective {
&& note.is_none() && note.is_none()
{ {
if let Some(items) = item.meta_item_list() { if let Some(items) = item.meta_item_list() {
if let Ok(subcommand) = match Self::parse(tcx, item_def_id, &items, item.span(), false) {
Self::parse(tcx, item_def_id, &items, item.span(), false) Ok(subcommand) => subcommands.push(subcommand),
{ Err(reported) => errored = Some(reported),
subcommands.push(subcommand); };
} else {
errored = true;
}
continue; continue;
} }
} else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
@ -163,8 +159,8 @@ impl<'tcx> OnUnimplementedDirective {
); );
} }
if errored { if let Some(reported) = errored {
Err(ErrorGuaranteed) Err(reported)
} else { } else {
Ok(OnUnimplementedDirective { Ok(OnUnimplementedDirective {
condition, condition,
@ -203,7 +199,9 @@ impl<'tcx> OnUnimplementedDirective {
append_const_msg: None, append_const_msg: None,
})) }))
} else { } else {
return Err(ErrorGuaranteed); let reported =
tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str");
return Err(reported);
}; };
debug!("of_item({:?}) = {:?}", item_def_id, result); debug!("of_item({:?}) = {:?}", item_def_id, result);
result result
@ -327,7 +325,7 @@ impl<'tcx> OnUnimplementedFormatString {
match generics.params.iter().find(|param| param.name == s) { match generics.params.iter().find(|param| param.name == s) {
Some(_) => (), Some(_) => (),
None => { None => {
struct_span_err!( let reported = struct_span_err!(
tcx.sess, tcx.sess,
span, span,
E0230, E0230,
@ -340,20 +338,20 @@ impl<'tcx> OnUnimplementedFormatString {
} }
) )
.emit(); .emit();
result = Err(ErrorGuaranteed); result = Err(reported);
} }
} }
} }
// `{:1}` and `{}` are not to be used // `{:1}` and `{}` are not to be used
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => { Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
struct_span_err!( let reported = struct_span_err!(
tcx.sess, tcx.sess,
span, span,
E0231, E0231,
"only named substitution parameters are allowed" "only named substitution parameters are allowed"
) )
.emit(); .emit();
result = Err(ErrorGuaranteed); result = Err(reported);
} }
}, },
} }

View file

@ -1396,7 +1396,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// `rustc_ty_utils::instance::resolve_associated_item()`. // `rustc_ty_utils::instance::resolve_associated_item()`.
let node_item = let node_item =
assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id) assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
.map_err(|ErrorGuaranteed| ())?; .map_err(|ErrorGuaranteed { .. }| ())?;
if node_item.is_final() { if node_item.is_final() {
// Non-specializable items are always projectable. // Non-specializable items are always projectable.

View file

@ -29,7 +29,7 @@ use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey; use crate::traits::ProjectionCacheKey;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_errors::Diagnostic;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::LateBoundRegionConversionTime;
@ -674,8 +674,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Err(_) => Ok(EvaluatedToErr), Err(_) => Ok(EvaluatedToErr),
} }
} }
(Err(ErrorHandled::Reported(ErrorGuaranteed)), _) (Err(ErrorHandled::Reported(_)), _)
| (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => Ok(EvaluatedToErr), | (_, Err(ErrorHandled::Reported(_))) => Ok(EvaluatedToErr),
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
span_bug!( span_bug!(
obligation.cause.span(self.tcx()), obligation.cause.span(self.tcx()),

View file

@ -16,14 +16,14 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err; use rustc_errors::{struct_span_err, EmissionGuarantee};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
use rustc_span::DUMMY_SP; use rustc_span::{Span, DUMMY_SP};
use super::util::impl_trait_ref_and_oblig; use super::util::impl_trait_ref_and_oblig;
use super::{FulfillmentContext, SelectionContext}; use super::{FulfillmentContext, SelectionContext};
@ -377,8 +377,7 @@ fn report_negative_positive_conflict(
} }
} }
sg.has_errored = true; sg.has_errored = Some(err.emit());
err.emit();
} }
fn report_conflicting_impls( fn report_conflicting_impls(
@ -394,7 +393,13 @@ fn report_conflicting_impls(
// Work to be done after we've built the DiagnosticBuilder. We have to define it // Work to be done after we've built the DiagnosticBuilder. We have to define it
// now because the struct_lint methods don't return back the DiagnosticBuilder // now because the struct_lint methods don't return back the DiagnosticBuilder
// that's passed in. // that's passed in.
let decorate = |err: LintDiagnosticBuilder<'_>| { fn decorate<G: EmissionGuarantee>(
tcx: TyCtxt<'_>,
overlap: OverlapError,
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
impl_span: Span,
err: LintDiagnosticBuilder<'_, G>,
) -> G {
let msg = format!( let msg = format!(
"conflicting implementations of trait `{}`{}{}", "conflicting implementations of trait `{}`{}{}",
overlap.trait_desc, overlap.trait_desc,
@ -440,17 +445,25 @@ fn report_conflicting_impls(
coherence::add_placeholder_note(&mut err); coherence::add_placeholder_note(&mut err);
} }
err.emit() err.emit()
}; }
match used_to_be_allowed { match used_to_be_allowed {
None => { None => {
sg.has_errored = true; let reported = if overlap.with_impl.is_local()
if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) { || !tcx.orphan_check_crate(()).contains(&impl_def_id)
{
let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
decorate(LintDiagnosticBuilder::new(err.forget_guarantee())); Some(decorate(
tcx,
overlap,
used_to_be_allowed,
impl_span,
LintDiagnosticBuilder::new(err),
))
} else { } else {
tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"); Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
} };
sg.has_errored = reported;
} }
Some(kind) => { Some(kind) => {
let lint = match kind { let lint = match kind {
@ -461,8 +474,10 @@ fn report_conflicting_impls(
lint, lint,
tcx.hir().local_def_id_to_hir_id(impl_def_id), tcx.hir().local_def_id_to_hir_id(impl_def_id),
impl_span, impl_span,
decorate, |ldb| {
) decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb);
},
);
} }
}; };
} }

View file

@ -306,9 +306,9 @@ fn resolve_associated_item<'tcx>(
resolved_ty, resolved_ty,
); );
let span = tcx.def_span(leaf_def.item.def_id); let span = tcx.def_span(leaf_def.item.def_id);
tcx.sess.delay_span_bug(span, &msg); let reported = tcx.sess.delay_span_bug(span, &msg);
return Err(ErrorGuaranteed); return Err(reported);
} }
} }

View file

@ -1,6 +1,6 @@
use crate::astconv::AstConv; use crate::astconv::AstConv;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::ty; use rustc_middle::ty;
@ -195,7 +195,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty_param_name: &str, ty_param_name: &str,
assoc_name: Ident, assoc_name: Ident,
span: Span, span: Span,
) where ) -> ErrorGuaranteed
where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>, I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
{ {
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
@ -231,7 +232,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.span_label(span, format!("associated type `{}` not found", assoc_name)); err.span_label(span, format!("associated type `{}` not found", assoc_name));
} }
err.emit(); err.emit()
} }
/// When there are any missing associated types, emit an E0191 error and attempt to supply a /// When there are any missing associated types, emit an E0191 error and attempt to supply a

View file

@ -6,7 +6,7 @@ use crate::astconv::{
use crate::errors::AssocTypeBindingNotAllowed; use crate::errors::AssocTypeBindingNotAllowed;
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
use rustc_ast::ast::ParamKindOrd; use rustc_ast::ast::ParamKindOrd;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_errors::{struct_span_err, Applicability, Diagnostic};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -456,28 +456,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut invalid_args = vec![]; let mut invalid_args = vec![];
let mut check_lifetime_args = |min_expected_args: usize, let mut check_lifetime_args =
|min_expected_args: usize,
max_expected_args: usize, max_expected_args: usize,
provided_args: usize, provided_args: usize,
late_bounds_ignore: bool| late_bounds_ignore: bool| {
-> bool {
if (min_expected_args..=max_expected_args).contains(&provided_args) { if (min_expected_args..=max_expected_args).contains(&provided_args) {
return true; return Ok(());
} }
if late_bounds_ignore { if late_bounds_ignore {
return true; return Ok(());
} }
if provided_args > max_expected_args { if provided_args > max_expected_args {
invalid_args.extend( invalid_args.extend(
gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()), gen_args.args[max_expected_args..provided_args]
.iter()
.map(|arg| arg.span()),
); );
}; };
let gen_args_info = if provided_args > min_expected_args { let gen_args_info = if provided_args > min_expected_args {
invalid_args.extend( invalid_args.extend(
gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()), gen_args.args[min_expected_args..provided_args]
.iter()
.map(|arg| arg.span()),
); );
let num_redundant_args = provided_args - min_expected_args; let num_redundant_args = provided_args - min_expected_args;
GenericArgsInfo::ExcessLifetimes { num_redundant_args } GenericArgsInfo::ExcessLifetimes { num_redundant_args }
@ -486,7 +490,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericArgsInfo::MissingLifetimes { num_missing_args } GenericArgsInfo::MissingLifetimes { num_missing_args }
}; };
WrongNumberOfGenericArgs::new( let reported = WrongNumberOfGenericArgs::new(
tcx, tcx,
gen_args_info, gen_args_info,
seg, seg,
@ -498,7 +502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.diagnostic() .diagnostic()
.emit(); .emit();
false Err(reported)
}; };
let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes }; let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
@ -527,7 +531,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"check_types_and_consts" "check_types_and_consts"
); );
if (expected_min..=expected_max).contains(&provided) { if (expected_min..=expected_max).contains(&provided) {
return true; return Ok(());
} }
let num_default_params = expected_max - expected_min; let num_default_params = expected_max - expected_min;
@ -561,7 +565,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!(?gen_args_info); debug!(?gen_args_info);
WrongNumberOfGenericArgs::new( let reported = WrongNumberOfGenericArgs::new(
tcx, tcx,
gen_args_info, gen_args_info,
seg, seg,
@ -573,7 +577,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.diagnostic() .diagnostic()
.emit_unless(gen_args.has_err()); .emit_unless(gen_args.has_err());
false Err(reported)
}; };
let args_correct = { let args_correct = {
@ -599,11 +603,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericArgCountResult { GenericArgCountResult {
explicit_late_bound, explicit_late_bound,
correct: if lifetimes_correct && args_correct { correct: lifetimes_correct.and(args_correct).map_err(|reported| {
Ok(()) GenericArgCountMismatch { reported: Some(reported), invalid_args }
} else { }),
Err(GenericArgCountMismatch { reported: Some(ErrorGuaranteed), invalid_args })
},
} }
} }
@ -700,7 +702,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
LATE_BOUND_LIFETIME_ARGUMENTS, LATE_BOUND_LIFETIME_ARGUMENTS,
args.args[0].id(), args.args[0].id(),
multispan, multispan,
|lint| lint.build(msg).emit(), |lint| {
lint.build(msg).emit();
},
); );
} }

View file

@ -1570,7 +1570,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
type_str: &str, type_str: &str,
trait_str: &str, trait_str: &str,
name: Symbol, name: Symbol,
) { ) -> ErrorGuaranteed {
let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type"); let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
if let (true, Ok(snippet)) = ( if let (true, Ok(snippet)) = (
self.tcx() self.tcx()
@ -1594,7 +1594,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Applicability::HasPlaceholders, Applicability::HasPlaceholders,
); );
} }
err.emit(); err.emit()
} }
// Search for a bound on a type parameter which includes the associated item // Search for a bound on a type parameter which includes the associated item
@ -1661,13 +1661,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(Some(bound), _) => (bound, matching_candidates.next()), (Some(bound), _) => (bound, matching_candidates.next()),
(None, Some(bound)) => (bound, const_candidates.next()), (None, Some(bound)) => (bound, const_candidates.next()),
(None, None) => { (None, None) => {
self.complain_about_assoc_type_not_found( let reported = self.complain_about_assoc_type_not_found(
all_candidates, all_candidates,
&ty_param_name(), &ty_param_name(),
assoc_name, assoc_name,
span, span,
); );
return Err(ErrorGuaranteed); return Err(reported);
} }
}; };
debug!("one_bound_for_assoc_type: bound = {:?}", bound); debug!("one_bound_for_assoc_type: bound = {:?}", bound);
@ -1752,9 +1752,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
where_bounds.join(",\n"), where_bounds.join(",\n"),
)); ));
} }
err.emit(); let reported = err.emit();
if !where_bounds.is_empty() { if !where_bounds.is_empty() {
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
@ -1811,7 +1811,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// trait reference. // trait reference.
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
// A cycle error occurred, most likely. // A cycle error occurred, most likely.
return Err(ErrorGuaranteed); let guar = tcx.sess.delay_span_bug(span, "expected cycle error");
return Err(guar);
}; };
self.one_bound_for_assoc_type( self.one_bound_for_assoc_type(
@ -1828,10 +1829,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
| Res::Def(DefKind::TyParam, param_did), | Res::Def(DefKind::TyParam, param_did),
) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?, ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
_ => { _ => {
if variant_resolution.is_some() { let reported = if variant_resolution.is_some() {
// Variant in type position // Variant in type position
let msg = format!("expected type, found variant `{}`", assoc_ident); let msg = format!("expected type, found variant `{}`", assoc_ident);
tcx.sess.span_err(span, &msg); tcx.sess.span_err(span, &msg)
} else if qself_ty.is_enum() { } else if qself_ty.is_enum() {
let mut err = struct_span_err!( let mut err = struct_span_err!(
tcx.sess, tcx.sess,
@ -1870,17 +1871,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.span_label(sp, format!("variant `{}` not found here", assoc_ident)); err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
} }
err.emit(); err.emit()
} else if !qself_ty.references_error() { } else if let Some(reported) = qself_ty.error_reported() {
reported
} else {
// Don't print `TyErr` to the user. // Don't print `TyErr` to the user.
self.report_ambiguous_associated_type( self.report_ambiguous_associated_type(
span, span,
&qself_ty.to_string(), &qself_ty.to_string(),
"Trait", "Trait",
assoc_ident.name, assoc_ident.name,
); )
} };
return Err(ErrorGuaranteed); return Err(reported);
} }
}; };
@ -1898,8 +1901,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// but it was used in a type position. // but it was used in a type position.
let Some(item) = item else { let Some(item) = item else {
let msg = format!("found associated const `{assoc_ident}` when type was expected"); let msg = format!("found associated const `{assoc_ident}` when type was expected");
tcx.sess.struct_span_err(span, &msg).emit(); let guar = tcx.sess.struct_span_err(span, &msg).emit();
return Err(ErrorGuaranteed); return Err(guar);
}; };
let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
@ -2737,7 +2740,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
sugg, sugg,
Applicability::MachineApplicable, Applicability::MachineApplicable,
) )
.emit() .emit();
}, },
); );
} }

View file

@ -91,8 +91,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let t = self.resolve_vars_if_possible(t); let t = self.resolve_vars_if_possible(t);
if t.references_error() { if let Some(reported) = t.error_reported() {
return Err(ErrorGuaranteed); return Err(reported);
} }
if self.type_is_known_to_be_sized_modulo_regions(t, span) { if self.type_is_known_to_be_sized_modulo_regions(t, span) {
@ -139,10 +139,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::Adt(..) | ty::Adt(..)
| ty::Never | ty::Never
| ty::Error(_) => { | ty::Error(_) => {
self.tcx let reported = self
.tcx
.sess .sess
.delay_span_bug(span, &format!("`{:?}` should be sized but is not?", t)); .delay_span_bug(span, &format!("`{:?}` should be sized but is not?", t));
return Err(ErrorGuaranteed); return Err(reported);
} }
}) })
} }
@ -174,7 +175,7 @@ pub enum CastError {
} }
impl From<ErrorGuaranteed> for CastError { impl From<ErrorGuaranteed> for CastError {
fn from(ErrorGuaranteed: ErrorGuaranteed) -> Self { fn from(_: ErrorGuaranteed) -> Self {
CastError::ErrorGuaranteed CastError::ErrorGuaranteed
} }
} }
@ -213,8 +214,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
// inference is more completely known. // inference is more completely known.
match cast_ty.kind() { match cast_ty.kind() {
ty::Dynamic(..) | ty::Slice(..) => { ty::Dynamic(..) | ty::Slice(..) => {
check.report_cast_to_unsized_type(fcx); let reported = check.report_cast_to_unsized_type(fcx);
Err(ErrorGuaranteed) Err(reported)
} }
_ => Ok(check), _ => Ok(check),
} }
@ -588,9 +589,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
} }
} }
fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) { fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) -> ErrorGuaranteed {
if self.cast_ty.references_error() || self.expr_ty.references_error() { if let Some(reported) =
return; self.cast_ty.error_reported().or_else(|| self.expr_ty.error_reported())
{
return reported;
} }
let tstr = fcx.ty_to_string(self.cast_ty); let tstr = fcx.ty_to_string(self.cast_ty);
@ -651,7 +654,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_help(self.expr.span, "consider using a box or reference as appropriate"); err.span_help(self.expr.span, "consider using a box or reference as appropriate");
} }
} }
err.emit(); err.emit()
} }
fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {

View file

@ -49,7 +49,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
} }
None => { None => {
tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
lint.build("use of calling convention not supported on this target").emit() lint.build("use of calling convention not supported on this target").emit();
}); });
} }
} }
@ -136,7 +136,7 @@ pub(super) fn check_fn<'a, 'tcx>(
}; };
if let Some(header) = item { if let Some(header) = item {
tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple") tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
} }
}; };
@ -625,11 +625,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
origin: &hir::OpaqueTyOrigin, origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
match origin { let reported = match origin {
hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span), hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
_ => opaque_type_cycle_error(tcx, def_id, span), _ => opaque_type_cycle_error(tcx, def_id, span),
} };
Err(ErrorGuaranteed) Err(reported)
} else { } else {
Ok(()) Ok(())
} }
@ -680,13 +680,15 @@ fn check_opaque_meets_bounds<'tcx>(
trace!(?hidden_type); trace!(?hidden_type);
match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) { match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) {
Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
Err(ty_err) => tcx.sess.delay_span_bug( Err(ty_err) => {
tcx.sess.delay_span_bug(
span, span,
&format!( &format!(
"could not check bounds on revealed type `{}`:\n{}", "could not check bounds on revealed type `{}`:\n{}",
hidden_type, ty_err, hidden_type, ty_err,
), ),
), );
}
} }
} }
@ -1422,7 +1424,7 @@ pub(super) fn check_type_params_are_used<'tcx>(
if ty.references_error() { if ty.references_error() {
// If there is already another error, do not emit // If there is already another error, do not emit
// an error for not using a type parameter. // an error for not using a type parameter.
assert!(tcx.sess.has_errors()); assert!(tcx.sess.has_errors().is_some());
return; return;
} }
@ -1463,14 +1465,14 @@ pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed;
pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed; pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed;
fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) { fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing") struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
.span_label(span, "recursive `async fn`") .span_label(span, "recursive `async fn`")
.note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`") .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
.note( .note(
"consider using the `async_recursion` crate: https://crates.io/crates/async_recursion", "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
) )
.emit(); .emit()
} }
/// Emit an error for recursive opaque types. /// Emit an error for recursive opaque types.
@ -1481,7 +1483,7 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) {
/// ///
/// If all the return expressions evaluate to `!`, then we explain that the error will go away /// If all the return expressions evaluate to `!`, then we explain that the error will go away
/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> ErrorGuaranteed {
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type"); let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
let mut label = false; let mut label = false;
@ -1550,5 +1552,5 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
if !label { if !label {
err.span_label(span, "cannot resolve opaque type"); err.span_label(span, "cannot resolve opaque type");
} }
err.emit(); err.emit()
} }

View file

@ -41,35 +41,30 @@ crate fn compare_impl_method<'tcx>(
let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span); let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span);
if let Err(ErrorGuaranteed) = if let Err(_) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) {
compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
{
return; return;
} }
if let Err(ErrorGuaranteed) = if let Err(_) = compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
{
return; return;
} }
if let Err(ErrorGuaranteed) = if let Err(_) =
compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span) compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
{ {
return; return;
} }
if let Err(ErrorGuaranteed) = compare_synthetic_generics(tcx, impl_m, trait_m) { if let Err(_) = compare_synthetic_generics(tcx, impl_m, trait_m) {
return; return;
} }
if let Err(ErrorGuaranteed) = if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
{ {
return; return;
} }
if let Err(ErrorGuaranteed) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) { if let Err(_) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) {
return; return;
} }
} }
@ -385,16 +380,16 @@ fn compare_predicate_entailment<'tcx>(
&terr, &terr,
false, false,
); );
diag.emit();
return Err(ErrorGuaranteed); return Err(diag.emit());
} }
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
// version. // version.
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
if !errors.is_empty() { if !errors.is_empty() {
infcx.report_fulfillment_errors(&errors, None, false); let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorGuaranteed); return Err(reported);
} }
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
@ -450,13 +445,13 @@ fn check_region_bounds_on_impl_item<'tcx>(
.map_or(def_sp, |g| g.span) .map_or(def_sp, |g| g.span)
}); });
tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait { let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
span, span,
item_kind, item_kind,
ident: impl_m.ident(tcx), ident: impl_m.ident(tcx),
generics_span, generics_span,
}); });
return Err(ErrorGuaranteed); return Err(reported);
} }
Ok(()) Ok(())
@ -550,8 +545,8 @@ fn compare_self_type<'tcx>(
} else { } else {
err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx)); err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
} }
err.emit(); let reported = err.emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
(true, false) => { (true, false) => {
@ -570,8 +565,8 @@ fn compare_self_type<'tcx>(
} else { } else {
err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx)); err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
} }
err.emit(); let reported = err.emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
@ -595,11 +590,9 @@ fn compare_number_of_generics<'tcx>(
let item_kind = assoc_item_kind_str(impl_); let item_kind = assoc_item_kind_str(impl_);
let mut err_occurred = false; let mut err_occurred = None;
for (kind, trait_count, impl_count) in matchings { for (kind, trait_count, impl_count) in matchings {
if impl_count != trait_count { if impl_count != trait_count {
err_occurred = true;
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() { let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
let trait_item = tcx.hir().expect_trait_item(def_id); let trait_item = tcx.hir().expect_trait_item(def_id);
if trait_item.generics.params.is_empty() { if trait_item.generics.params.is_empty() {
@ -690,11 +683,12 @@ fn compare_number_of_generics<'tcx>(
err.span_label(*span, "`impl Trait` introduces an implicit type parameter"); err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
} }
err.emit(); let reported = err.emit();
err_occurred = Some(reported);
} }
} }
if err_occurred { Err(ErrorGuaranteed) } else { Ok(()) } if let Some(reported) = err_occurred { Err(reported) } else { Ok(()) }
} }
fn compare_number_of_method_arguments<'tcx>( fn compare_number_of_method_arguments<'tcx>(
@ -772,8 +766,8 @@ fn compare_number_of_method_arguments<'tcx>(
impl_number_args impl_number_args
), ),
); );
err.emit(); let reported = err.emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
Ok(()) Ok(())
@ -789,7 +783,7 @@ fn compare_synthetic_generics<'tcx>(
// 2. Explanation as to what is going on // 2. Explanation as to what is going on
// If we get here, we already have the same number of generics, so the zip will // If we get here, we already have the same number of generics, so the zip will
// be okay. // be okay.
let mut error_found = false; let mut error_found = None;
let impl_m_generics = tcx.generics_of(impl_m.def_id); let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id); let trait_m_generics = tcx.generics_of(trait_m.def_id);
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind { let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
@ -918,11 +912,11 @@ fn compare_synthetic_generics<'tcx>(
} }
_ => unreachable!(), _ => unreachable!(),
} }
err.emit(); let reported = err.emit();
error_found = true; error_found = Some(reported);
} }
} }
if error_found { Err(ErrorGuaranteed) } else { Ok(()) } if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
} }
fn compare_const_param_types<'tcx>( fn compare_const_param_types<'tcx>(
@ -979,8 +973,8 @@ fn compare_const_param_types<'tcx>(
trait_ty trait_ty
), ),
); );
err.emit(); let reported = err.emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
@ -1203,8 +1197,8 @@ fn compare_type_predicate_entailment<'tcx>(
// version. // version.
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
if !errors.is_empty() { if !errors.is_empty() {
infcx.report_fulfillment_errors(&errors, None, false); let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorGuaranteed); return Err(reported);
} }
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
@ -1427,8 +1421,8 @@ pub fn check_type_bounds<'tcx>(
// version. // version.
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
if !errors.is_empty() { if !errors.is_empty() {
infcx.report_fulfillment_errors(&errors, None, false); let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorGuaranteed); return Err(reported);
} }
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of

View file

@ -55,11 +55,11 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
// already checked by coherence, but compilation may // already checked by coherence, but compilation may
// not have been terminated. // not have been terminated.
let span = tcx.def_span(drop_impl_did); let span = tcx.def_span(drop_impl_did);
tcx.sess.delay_span_bug( let reported = tcx.sess.delay_span_bug(
span, span,
&format!("should have been rejected by coherence check: {}", dtor_self_type), &format!("should have been rejected by coherence check: {}", dtor_self_type),
); );
Err(ErrorGuaranteed) Err(reported)
} }
} }
} }
@ -94,7 +94,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
Err(_) => { Err(_) => {
let item_span = tcx.def_span(self_type_did); let item_span = tcx.def_span(self_type_did);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
struct_span_err!( let reported = struct_span_err!(
tcx.sess, tcx.sess,
drop_impl_span, drop_impl_span,
E0366, E0366,
@ -109,15 +109,15 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
), ),
) )
.emit(); .emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
let errors = fulfillment_cx.select_all_or_error(&infcx); let errors = fulfillment_cx.select_all_or_error(&infcx);
if !errors.is_empty() { if !errors.is_empty() {
// this could be reached when we get lazy normalization // this could be reached when we get lazy normalization
infcx.report_fulfillment_errors(&errors, None, false); let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorGuaranteed); return Err(reported);
} }
// NB. It seems a bit... suspicious to use an empty param-env // NB. It seems a bit... suspicious to use an empty param-env
@ -258,7 +258,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) { if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) {
let item_span = tcx.def_span(self_type_did); let item_span = tcx.def_span(self_type_did);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id()); let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id());
struct_span_err!( let reported = struct_span_err!(
tcx.sess, tcx.sess,
predicate_sp, predicate_sp,
E0367, E0367,
@ -268,7 +268,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
) )
.span_note(item_span, "the implementor must specify the same requirement") .span_note(item_span, "the implementor must specify the same requirement")
.emit(); .emit();
result = Err(ErrorGuaranteed); result = Err(reported);
} }
} }

View file

@ -667,7 +667,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// else an error would have been flagged by the // else an error would have been flagged by the
// `loops` pass for using break with an expression // `loops` pass for using break with an expression
// where you are not supposed to. // where you are not supposed to.
assert!(expr_opt.is_none() || self.tcx.sess.has_errors()); assert!(expr_opt.is_none() || self.tcx.sess.has_errors().is_some());
} }
// If we encountered a `break`, then (no surprise) it may be possible to break from the // If we encountered a `break`, then (no surprise) it may be possible to break from the
@ -1187,7 +1187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
deferred_cast_checks.push(cast_check); deferred_cast_checks.push(cast_check);
t_cast t_cast
} }
Err(ErrorGuaranteed) => self.tcx.ty_error(), Err(_) => self.tcx.ty_error(),
} }
} }
} }

View file

@ -315,7 +315,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
// FIXME: currently we never try to compose autoderefs // FIXME: currently we never try to compose autoderefs
// and ReifyFnPointer/UnsafeFnPointer, but we could. // and ReifyFnPointer/UnsafeFnPointer, but we could.
_ => self.tcx.sess.delay_span_bug( _ => {
self.tcx.sess.delay_span_bug(
expr.span, expr.span,
&format!( &format!(
"while adjusting {:?}, can't compose {:?} and {:?}", "while adjusting {:?}, can't compose {:?} and {:?}",
@ -323,8 +324,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
entry.get(), entry.get(),
adj adj
), ),
), );
}; }
}
*entry.get_mut() = adj; *entry.get_mut() = adj;
} }
} }
@ -903,7 +905,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.or_else(|error| { .or_else(|error| {
let result = match error { let result = match error {
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
_ => Err(ErrorGuaranteed), _ => Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()),
}; };
// If we have a path like `MyTrait::missing_method`, then don't register // If we have a path like `MyTrait::missing_method`, then don't register

View file

@ -412,7 +412,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lint::builtin::TYVAR_BEHIND_RAW_POINTER, lint::builtin::TYVAR_BEHIND_RAW_POINTER,
scope_expr_id, scope_expr_id,
span, span,
|lint| lint.build("type annotations needed").emit(), |lint| {
lint.build("type annotations needed").emit();
},
); );
} }
} else { } else {

View file

@ -81,7 +81,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.is_tainted_by_errors() { if self.is_tainted_by_errors() {
// FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted. // FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted.
wbcx.typeck_results.tainted_by_errors = Some(ErrorGuaranteed); wbcx.typeck_results.tainted_by_errors =
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
} }
debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results); debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
@ -662,7 +663,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
// users of the typeck results don't produce extra errors, or worse, ICEs. // users of the typeck results don't produce extra errors, or worse, ICEs.
if resolver.replaced_with_error { if resolver.replaced_with_error {
// FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted. // FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted.
self.typeck_results.tainted_by_errors = Some(ErrorGuaranteed); self.typeck_results.tainted_by_errors =
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
} }
x x
@ -707,7 +709,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
} }
fn report_type_error(&self, t: Ty<'tcx>) { fn report_type_error(&self, t: Ty<'tcx>) {
if !self.tcx.sess.has_errors() { if !self.tcx.sess.has_errors().is_some() {
self.infcx self.infcx
.emit_inference_failure_err( .emit_inference_failure_err(
Some(self.body.id()), Some(self.body.id()),
@ -721,7 +723,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
} }
fn report_const_error(&self, c: ty::Const<'tcx>) { fn report_const_error(&self, c: ty::Const<'tcx>) {
if !self.tcx.sess.has_errors() { if self.tcx.sess.has_errors().is_none() {
self.infcx self.infcx
.emit_inference_failure_err( .emit_inference_failure_err(
Some(self.body.id()), Some(self.body.id()),

View file

@ -21,7 +21,7 @@ pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
for &impl_of_trait in impls_of_trait { for &impl_of_trait in impls_of_trait {
match orphan_check_impl(tcx, impl_of_trait) { match orphan_check_impl(tcx, impl_of_trait) {
Ok(()) => {} Ok(()) => {}
Err(ErrorGuaranteed) => errors.push(impl_of_trait), Err(_) => errors.push(impl_of_trait),
} }
} }
@ -135,17 +135,19 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
}; };
if let Some((msg, label)) = msg { if let Some((msg, label)) = msg {
let reported =
struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit(); struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
} }
if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() { if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
tcx.sess let reported = tcx
.sess
.struct_span_err(sp, "cannot implement trait on type alias impl trait") .struct_span_err(sp, "cannot implement trait on type alias impl trait")
.span_note(tcx.def_span(def_id), "type alias impl trait defined here") .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
.emit(); .emit();
return Err(ErrorGuaranteed); return Err(reported);
} }
Ok(()) Ok(())

View file

@ -1,4 +1,4 @@
use rustc_errors::{Applicability, ErrorGuaranteed, StashKey}; use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
@ -366,7 +366,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
owner, def_id, owner, def_id,
), ),
); );
if let Some(ErrorGuaranteed) = if let Some(_) =
tcx.typeck(owner).tainted_by_errors tcx.typeck(owner).tainted_by_errors
{ {
// Some error in the // Some error in the

View file

@ -523,7 +523,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
// struct; however, when EUV is run during typeck, it // struct; however, when EUV is run during typeck, it
// may not. This will generate an error earlier in typeck, // may not. This will generate an error earlier in typeck,
// so we can just ignore it. // so we can just ignore it.
if !self.tcx().sess.has_errors() { if !self.tcx().sess.has_errors().is_some() {
span_bug!(with_expr.span, "with expression doesn't evaluate to a struct"); span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
} }
} }

View file

@ -537,7 +537,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
check_unused::check_crate(tcx); check_unused::check_crate(tcx);
check_for_entry_fn(tcx); check_for_entry_fn(tcx);
if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorGuaranteed) } if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
} }
/// A quasi-deprecated helper used in rustdoc and clippy to get /// A quasi-deprecated helper used in rustdoc and clippy to get

View file

@ -834,7 +834,9 @@ impl AttributesExt for [ast::Attribute] {
{ {
match Cfg::parse(cfg_mi) { match Cfg::parse(cfg_mi) {
Ok(new_cfg) => cfg &= new_cfg, Ok(new_cfg) => cfg &= new_cfg,
Err(e) => sess.span_err(e.span, e.msg), Err(e) => {
sess.span_err(e.span, e.msg);
}
} }
} }
} }

View file

@ -452,7 +452,7 @@ crate fn run_global_ctxt(
} }
} }
if tcx.sess.diagnostic().has_errors_or_lint_errors() { if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
rustc_errors::FatalError.raise(); rustc_errors::FatalError.raise();
} }

View file

@ -149,7 +149,7 @@ crate fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
collector collector
}); });
if compiler.session().diagnostic().has_errors_or_lint_errors() { if compiler.session().diagnostic().has_errors_or_lint_errors().is_some() {
FatalError.raise(); FatalError.raise();
} }

View file

@ -179,7 +179,7 @@ pub fn main() {
let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() { let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() {
Some(args) => main_args(&args), Some(args) => main_args(&args),
_ => Err(ErrorGuaranteed), _ => Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()),
}); });
process::exit(exit_code); process::exit(exit_code);
} }
@ -692,7 +692,13 @@ fn main_args(at_args: &[String]) -> MainResult {
// codes from `from_matches` here. // codes from `from_matches` here.
let options = match config::Options::from_matches(&matches) { let options = match config::Options::from_matches(&matches) {
Ok(opts) => opts, Ok(opts) => opts,
Err(code) => return if code == 0 { Ok(()) } else { Err(ErrorGuaranteed) }, Err(code) => {
return if code == 0 {
Ok(())
} else {
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
};
}
}; };
rustc_interface::util::run_in_thread_pool_with_globals( rustc_interface::util::run_in_thread_pool_with_globals(
options.edition, options.edition,
@ -705,8 +711,8 @@ fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainRes
match res { match res {
Ok(()) => Ok(()), Ok(()) => Ok(()),
Err(err) => { Err(err) => {
diag.struct_err(&err).emit(); let reported = diag.struct_err(&err).emit();
Err(ErrorGuaranteed) Err(reported)
} }
} }
} }
@ -790,7 +796,7 @@ fn main_options(options: config::Options) -> MainResult {
(resolver.clone(), resolver_caches) (resolver.clone(), resolver_caches)
}; };
if sess.diagnostic().has_errors_or_lint_errors() { if sess.diagnostic().has_errors_or_lint_errors().is_some() {
sess.fatal("Compilation failed, aborting rustdoc"); sess.fatal("Compilation failed, aborting rustdoc");
} }

View file

@ -80,7 +80,7 @@ impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
format!("<{}>", url), format!("<{}>", url),
Applicability::MachineApplicable, Applicability::MachineApplicable,
) )
.emit() .emit();
}); });
}; };

View file

@ -91,7 +91,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
// lambda that will use the lint to start a new diagnostic and add // lambda that will use the lint to start a new diagnostic and add
// a suggestion to it when needed. // a suggestion to it when needed.
let diag_builder = |lint: LintDiagnosticBuilder<'_>| { let diag_builder = |lint: LintDiagnosticBuilder<'_, ()>| {
let explanation = if is_ignore { let explanation = if is_ignore {
"`ignore` code blocks require valid Rust code for syntax highlighting; \ "`ignore` code blocks require valid Rust code for syntax highlighting; \
mark blocks that do not contain Rust code as text" mark blocks that do not contain Rust code as text"

View file

@ -125,7 +125,9 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
crate::lint::MISSING_DOC_CODE_EXAMPLES, crate::lint::MISSING_DOC_CODE_EXAMPLES,
hir_id, hir_id,
sp, sp,
|lint| lint.build("missing code example in this documentation").emit(), |lint| {
lint.build("missing code example in this documentation").emit();
},
); );
} }
} else if tests.found_tests > 0 } else if tests.found_tests > 0
@ -135,7 +137,9 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
crate::lint::PRIVATE_DOC_TESTS, crate::lint::PRIVATE_DOC_TESTS,
hir_id, hir_id,
item.attr_span(cx.tcx), item.attr_span(cx.tcx),
|lint| lint.build("documentation test in private item").emit(), |lint| {
lint.build("documentation test in private item").emit();
},
); );
} }
} }

View file

@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass {
let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr"); let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) { if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) {
cx.lint(MISSING_ALLOWED_ATTR, |lint| { cx.lint(MISSING_ALLOWED_ATTR, |lint| {
lint.build("Missing 'allowed_attr' attribute").set_span(span).emit() lint.build("Missing 'allowed_attr' attribute").set_span(span).emit();
}); });
} }
} }

View file

@ -34,7 +34,7 @@ macro_rules! fake_lint_pass {
if !cx.sess().contains_name(attrs, $attr) { if !cx.sess().contains_name(attrs, $attr) {
cx.lint(CRATE_NOT_OKAY, |lint| { cx.lint(CRATE_NOT_OKAY, |lint| {
let msg = format!("crate is not marked with #![{}]", $attr); let msg = format!("crate is not marked with #![{}]", $attr);
lint.build(&msg).set_span(span).emit() lint.build(&msg).set_span(span).emit();
}); });
} }
)* )*

View file

@ -30,7 +30,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
let span = cx.tcx.def_span(CRATE_DEF_ID); let span = cx.tcx.def_span(CRATE_DEF_ID);
if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) { if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) {
cx.lint(CRATE_NOT_OKAY, |lint| { cx.lint(CRATE_NOT_OKAY, |lint| {
lint.build("crate is not marked with #![crate_okay]").set_span(span).emit() lint.build("crate is not marked with #![crate_okay]").set_span(span).emit();
}); });
} }
} }

View file

@ -23,10 +23,10 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) { fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) {
match it.ident.as_str() { match it.ident.as_str() {
"lintme" => cx.lint(TEST_LINT, |lint| { "lintme" => cx.lint(TEST_LINT, |lint| {
lint.build("item is named 'lintme'").set_span(it.span).emit() lint.build("item is named 'lintme'").set_span(it.span).emit();
}), }),
"pleaselintme" => cx.lint(PLEASE_LINT, |lint| { "pleaselintme" => cx.lint(PLEASE_LINT, |lint| {
lint.build("item is named 'pleaselintme'").set_span(it.span).emit() lint.build("item is named 'pleaselintme'").set_span(it.span).emit();
}), }),
_ => {} _ => {}
} }

View file

@ -22,7 +22,7 @@ impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.name.as_str() == "lintme" { if it.ident.name.as_str() == "lintme" {
cx.lint(TEST_LINT, |lint| { cx.lint(TEST_LINT, |lint| {
lint.build("item is named 'lintme'").set_span(it.span).emit() lint.build("item is named 'lintme'").set_span(it.span).emit();
}); });
} }
} }

Some files were not shown because too many files have changed in this diff Show more