diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index cdaa528e8e4..c01dcd94c72 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -302,6 +302,9 @@ pub struct Handler { inner: Lock, } +/// This inner struct exists to keep it all behind a single lock; +/// this is done to prevent possible deadlocks in a multi-threaded compiler, +/// as well as inconsistent state observation. struct HandlerInner { flags: HandlerFlags, /// The number of errors that have been emitted, including duplicates. @@ -382,52 +385,65 @@ impl Drop for HandlerInner { } impl Handler { - pub fn with_tty_emitter(color_config: ColorConfig, - can_emit_warnings: bool, - treat_err_as_bug: Option, - cm: Option>) - -> Handler { - Handler::with_tty_emitter_and_flags( + pub fn with_tty_emitter( + color_config: ColorConfig, + can_emit_warnings: bool, + treat_err_as_bug: Option, + cm: Option>, + ) -> Self { + Self::with_tty_emitter_and_flags( color_config, cm, HandlerFlags { can_emit_warnings, treat_err_as_bug, .. Default::default() - }) + }, + ) } - pub fn with_tty_emitter_and_flags(color_config: ColorConfig, - cm: Option>, - flags: HandlerFlags) - -> Handler { + pub fn with_tty_emitter_and_flags( + color_config: ColorConfig, + cm: Option>, + flags: HandlerFlags, + ) -> Self { let emitter = Box::new(EmitterWriter::stderr( - color_config, cm, false, false, None, flags.external_macro_backtrace)); - Handler::with_emitter_and_flags(emitter, flags) + color_config, + cm, + false, + false, + None, + flags.external_macro_backtrace, + )); + Self::with_emitter_and_flags(emitter, flags) } - pub fn with_emitter(can_emit_warnings: bool, - treat_err_as_bug: Option, - e: Box) - -> Handler { + pub fn with_emitter( + can_emit_warnings: bool, + treat_err_as_bug: Option, + emitter: Box, + ) -> Self { Handler::with_emitter_and_flags( - e, + emitter, HandlerFlags { can_emit_warnings, treat_err_as_bug, .. Default::default() - }) + }, + ) } - pub fn with_emitter_and_flags(e: Box, flags: HandlerFlags) -> Handler - { - Handler { + pub fn with_emitter_and_flags( + emitter: Box, + flags: HandlerFlags + ) -> Self { + Self { flags, inner: Lock::new(HandlerInner { flags, err_count: 0, deduplicated_err_count: 0, - emitter: e, + emitter, continue_after_error: true, delayed_span_bugs: Vec::new(), taught_diagnostics: Default::default(), @@ -474,7 +490,8 @@ impl Handler { "{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})", file!(), line!(), span, key )); - inner.emit_explicit_bug(&old_diag); + inner.emit_diag_at_span(old_diag, span); + panic!(ExplicitBug); } } @@ -492,34 +509,35 @@ impl Handler { self.inner.borrow_mut().emit_stashed_diagnostics(); } + /// Construct a dummy builder with `Level::Cancelled`. + /// + /// Using this will neither report anything to the user (e.g. a warning), + /// nor will compilation cancel as a result. pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Cancelled, "") } - pub fn struct_span_warn>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - result.set_span(sp); - if !self.flags.can_emit_warnings { - result.cancel(); - } + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + pub fn struct_span_warn(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { + let mut result = self.struct_warn(msg); + result.set_span(span); result } - pub fn struct_span_warn_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - result.set_span(sp); + + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// Also include a code. + pub fn struct_span_warn_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_span_warn(span, msg); result.code(code); - if !self.flags.can_emit_warnings { - result.cancel(); - } result } + + /// Construct a builder at the `Warning` level with the `msg`. pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); if !self.flags.can_emit_warnings { @@ -527,136 +545,141 @@ impl Handler { } result } - pub fn struct_span_err>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.set_span(sp); + + /// Construct a builder at the `Error` level at the given `span` and with the `msg`. + pub fn struct_span_err(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { + let mut result = self.struct_err(msg); + result.set_span(span); result } - pub fn struct_span_err_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.set_span(sp); + + /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`. + pub fn struct_span_err_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_span_err(span, msg); result.code(code); result } + + /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Error, msg) } - pub fn struct_err_with_code( + + /// Construct a builder at the `Error` level with the `msg` and the `code`. + pub fn struct_err_with_code(&self, msg: &str, code: DiagnosticId) -> DiagnosticBuilder<'_> { + let mut result = self.struct_err(msg); + result.code(code); + result + } + + /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. + pub fn struct_span_fatal( &self, + span: impl Into, + msg: &str, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_fatal(msg); + result.set_span(span); + result + } + + /// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`. + pub fn struct_span_fatal_with_code( + &self, + span: impl Into, msg: &str, code: DiagnosticId, ) -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.code(code); - result - } - pub fn struct_span_fatal>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg); - result.set_span(sp); - result - } - pub fn struct_span_fatal_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg); - result.set_span(sp); + let mut result = self.struct_span_fatal(span, msg); result.code(code); result } + + /// Construct a builder at the `Error` level with the `msg`. pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Fatal, msg) } - pub fn span_fatal>(&self, sp: S, msg: &str) -> FatalError { - self.emit_diagnostic(Diagnostic::new(Fatal, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + pub fn span_fatal(&self, span: impl Into, msg: &str) -> FatalError { + self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span); FatalError } - pub fn span_fatal_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> FatalError { - self.emit_diagnostic(Diagnostic::new_with_code(Fatal, Some(code), msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_fatal_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> FatalError { + self.emit_diag_at_span(Diagnostic::new_with_code(Fatal, Some(code), msg), span); FatalError } - pub fn span_err>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Error, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_err(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Error, msg), span); } - pub fn mut_span_err>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.set_span(sp); - result + + pub fn span_err_with_code(&self, span: impl Into, msg: &str, code: DiagnosticId) { + self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span); } - pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.emit_diagnostic(Diagnostic::new_with_code(Error, Some(code), msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_warn(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Warning, msg), span); } - pub fn span_warn>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Warning, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_warn_with_code(&self, span: impl Into, msg: &str, code: DiagnosticId) { + self.emit_diag_at_span(Diagnostic::new_with_code(Warning, Some(code), msg), span); } - pub fn span_warn_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.emit_diagnostic(Diagnostic::new_with_code(Warning, Some(code), msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_bug(&self, span: impl Into, msg: &str) -> ! { + self.inner.borrow_mut().span_bug(span, msg) } - pub fn span_bug>(&self, sp: S, msg: &str) -> ! { - self.inner.borrow_mut().span_bug(sp, msg) + + pub fn delay_span_bug(&self, span: impl Into, msg: &str) { + self.inner.borrow_mut().delay_span_bug(span, msg) } - pub fn delay_span_bug>(&self, sp: S, msg: &str) { - self.inner.borrow_mut().delay_span_bug(sp, msg) + + pub fn span_bug_no_panic(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Bug, msg), span); } - pub fn span_bug_no_panic>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Bug, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_note_without_error(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Note, msg), span); } - pub fn span_note_without_error>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Note, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); - } - pub fn span_note_diag(&self, - sp: Span, - msg: &str) - -> DiagnosticBuilder<'_> { + + pub fn span_note_diag(&self, span: Span, msg: &str) -> DiagnosticBuilder<'_> { let mut db = DiagnosticBuilder::new(self, Note, msg); - db.set_span(sp); + db.set_span(span); db } + pub fn failure(&self, msg: &str) { self.inner.borrow_mut().failure(msg); } + pub fn fatal(&self, msg: &str) -> FatalError { self.inner.borrow_mut().fatal(msg) } + pub fn err(&self, msg: &str) { self.inner.borrow_mut().err(msg); } + pub fn warn(&self, msg: &str) { let mut db = DiagnosticBuilder::new(self, Warning, msg); db.emit(); } + pub fn note_without_error(&self, msg: &str) { - let mut db = DiagnosticBuilder::new(self, Note, msg); - db.emit(); + DiagnosticBuilder::new(self, Note, msg).emit(); } + pub fn bug(&self, msg: &str) -> ! { self.inner.borrow_mut().bug(msg) } @@ -698,6 +721,12 @@ impl Handler { self.inner.borrow_mut().emit_diagnostic(diagnostic) } + fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into) { + let mut inner = self.inner.borrow_mut(); + inner.emit_diagnostic(diag.set_span(sp)); + inner.abort_if_errors_and_should_abort(); + } + pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) } @@ -837,17 +866,17 @@ impl HandlerInner { } } - fn span_bug>(&mut self, sp: S, msg: &str) -> ! { - self.emit_explicit_bug(Diagnostic::new(Bug, msg).set_span(sp)); - } - - fn emit_explicit_bug(&mut self, diag: &Diagnostic) -> ! { - self.emit_diagnostic(diag); - self.abort_if_errors_and_should_abort(); + fn span_bug(&mut self, sp: impl Into, msg: &str) -> ! { + self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp); panic!(ExplicitBug); } - fn delay_span_bug>(&mut self, sp: S, msg: &str) { + fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into) { + self.emit_diagnostic(diag.set_span(sp)); + self.abort_if_errors_and_should_abort(); + } + + fn delay_span_bug(&mut self, sp: impl Into, msg: &str) { if self.treat_err_as_bug() { // FIXME: don't abort here if report_delayed_bugs is off self.span_bug(sp, msg); @@ -862,18 +891,20 @@ impl HandlerInner { } fn fatal(&mut self, msg: &str) -> FatalError { - if self.treat_err_as_bug() { - self.bug(msg); - } - self.emit_diagnostic(&Diagnostic::new(Fatal, msg)); + self.emit_error(Fatal, msg); FatalError } fn err(&mut self, msg: &str) { + self.emit_error(Error, msg); + } + + /// Emit an error; level should be `Error` or `Fatal`. + fn emit_error(&mut self, level: Level, msg: &str,) { if self.treat_err_as_bug() { self.bug(msg); } - self.emit_diagnostic(&Diagnostic::new(Error, msg)); + self.emit_diagnostic(&Diagnostic::new(level, msg)); } fn bug(&mut self, msg: &str) -> ! { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b0e886a2aa2..f7e766bb84d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -832,7 +832,7 @@ fn check_method_receiver<'fcx, 'tcx>( } fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { - fcx.tcx.sess.diagnostic().mut_span_err( + fcx.tcx.sess.diagnostic().struct_span_err( span, &format!("invalid `self` parameter type: {:?}", receiver_ty) ).note("type of `self` must be `Self` or a type that dereferences to it") diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a6be5b10178..36d066b0269 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1041,10 +1041,6 @@ impl<'a> ExtCtxt<'a> { pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); } - pub fn mut_span_err>(&self, sp: S, msg: &str) - -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.mut_span_err(sp, msg) - } pub fn span_warn>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b80c530731d..c3b1f91d531 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -384,7 +384,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let attr = attr::find_by_name(item.attrs(), sym::derive) .expect("`derive` attribute should exist"); let span = attr.span; - let mut err = self.cx.mut_span_err(span, + let mut err = self.cx.struct_span_err(span, "`derive` may only be applied to structs, enums and unions"); if let ast::AttrStyle::Inner = attr.style { let trait_list = derives.iter() diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 26455df17b8..2765346b333 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -295,7 +295,7 @@ impl<'a, 'b> Context<'a, 'b> { .filter(|fmt| fmt.precision_span.is_some()) .count(); if self.names.is_empty() && !numbered_position_args && count != self.args.len() { - e = self.ecx.mut_span_err( + e = self.ecx.struct_span_err( sp, &format!( "{} positional argument{} in format string, but {}", @@ -336,7 +336,7 @@ impl<'a, 'b> Context<'a, 'b> { sp = MultiSpan::from_span(self.fmtsp); } - e = self.ecx.mut_span_err(sp, + e = self.ecx.struct_span_err(sp, &format!("invalid reference to positional {} ({})", arg_list, self.describe_num_args()));