Skip to content

Commit

Permalink
Rollup merge of rust-lang#64698 - Centril:infer-const-with-stash, r=e…
Browse files Browse the repository at this point in the history
…stebank

Recover on `const X = 42;` and infer type + Error Stash API

Here we:

1. Introduce a notion of the "error stash".

   This is a map in the `Handler` to which you can `err.stash(...)` away your diagnostics and then steal them in a later "phase" of the compiler (e.g. stash in parser, steal in typeck) to enrich them with more information that isn't available in the previous "phase".

    I believe I've covered all the bases to make sure these diagnostics are actually emitted eventually even under `#[cfg(FALSE)]` but please check my logic.

2. Recover when parsing `[const | static mut?] $ident = $expr;` which has a missing type.

    Use the "error stash" to stash away the error and later steal the error in typeck where we emit the error as `MachineApplicable` with the actual inferred type. This builds on rust-lang#62804.

cc rust-lang/rfcs#2545

r? @estebank
  • Loading branch information
Centril authored Sep 24, 2019
2 parents 6a4be43 + f70665a commit 0d0f753
Show file tree
Hide file tree
Showing 12 changed files with 447 additions and 188 deletions.
1 change: 1 addition & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ impl Session {
}
pub fn compile_status(&self) -> Result<(), ErrorReported> {
if self.has_errors() {
self.diagnostic().emit_stashed_diagnostics();
Err(ErrorReported)
} else {
Ok(())
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ pub fn run_compiler(
);
Ok(())
})?;
return sess.compile_status();
} else {
let mut krate = compiler.parse()?.take();
pretty::visit_crate(sess, &mut krate, ppm);
Expand All @@ -307,8 +306,8 @@ pub fn run_compiler(
ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
return sess.compile_status();
}
return sess.compile_status();
}

if callbacks.after_parsing(compiler) == Compilation::Stop {
Expand Down
41 changes: 28 additions & 13 deletions src/librustc_errors/diagnostic_builder.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use crate::Diagnostic;
use crate::DiagnosticId;
use crate::DiagnosticStyledString;
use crate::Applicability;
use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString};
use crate::{Applicability, Level, Handler, StashKey};

use crate::Level;
use crate::Handler;
use std::fmt::{self, Debug};
use std::ops::{Deref, DerefMut};
use std::thread::panicking;
Expand Down Expand Up @@ -117,18 +113,30 @@ impl<'a> DiagnosticBuilder<'a> {
}
}

/// Buffers the diagnostic for later emission, unless handler
/// has disabled such buffering.
pub fn buffer(mut self, buffered_diagnostics: &mut Vec<Diagnostic>) {
/// Stashes diagnostic for possible later improvement in a different,
/// later stage of the compiler. The diagnostic can be accessed with
/// the provided `span` and `key` through `.steal_diagnostic` on `Handler`.
///
/// As with `buffer`, this is unless the handler has disabled such buffering.
pub fn stash(self, span: Span, key: StashKey) {
if let Some((diag, handler)) = self.into_diagnostic() {
handler.stash_diagnostic(span, key, diag);
}
}

/// Converts the builder to a `Diagnostic` for later emission,
/// unless handler has disabled such buffering.
pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> {
if self.0.handler.flags.dont_buffer_diagnostics ||
self.0.handler.flags.treat_err_as_bug.is_some()
{
self.emit();
return;
return None;
}

// We need to use `ptr::read` because `DiagnosticBuilder`
// implements `Drop`.
let handler = self.0.handler;

// We need to use `ptr::read` because `DiagnosticBuilder` implements `Drop`.
let diagnostic;
unsafe {
diagnostic = std::ptr::read(&self.0.diagnostic);
Expand All @@ -137,7 +145,14 @@ impl<'a> DiagnosticBuilder<'a> {
// Logging here is useful to help track down where in logs an error was
// actually emitted.
debug!("buffer: diagnostic={:?}", diagnostic);
buffered_diagnostics.push(diagnostic);

Some((diagnostic, handler))
}

/// Buffers the diagnostic for later emission,
/// unless handler has disabled such buffering.
pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag));
}

/// Convenience function for internal use, clients should use one of the
Expand Down
Loading

0 comments on commit 0d0f753

Please sign in to comment.