about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <eddyb@lyken.rs>2022-01-24 09:19:33 +0000
committerEduard-Mihai Burtescu <eddyb@lyken.rs>2022-01-24 10:49:10 +0000
commit68fa81baa3acf3a93ce4b41c8366039229926fc2 (patch)
treec5df38fb546f41c444df071d4c0fb15927e46410 /compiler/rustc_errors/src
parent42313dd29b3edb0ab453a0d43d12876ec7e48ce0 (diff)
downloadrust-68fa81baa3acf3a93ce4b41c8366039229926fc2.tar.gz
rust-68fa81baa3acf3a93ce4b41c8366039229926fc2.zip
rustc_errors: remove `allow_suggestions` from `DiagnosticBuilder`.
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs38
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs138
-rw-r--r--compiler/rustc_errors/src/emitter.rs7
-rw-r--r--compiler/rustc_errors/src/json.rs2
4 files changed, 59 insertions, 126 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index e5116cd8dfe..8cfecafd20c 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -11,6 +11,11 @@ use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 
+/// Error type for `Diagnostic`'s `suggestions` field, indicating that
+/// `.disable_suggestions()` was called on the `Diagnostic`.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
+pub struct SuggestionsDisabled;
+
 #[must_use]
 #[derive(Clone, Debug, Encodable, Decodable)]
 pub struct Diagnostic {
@@ -19,7 +24,7 @@ pub struct Diagnostic {
     pub code: Option<DiagnosticId>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
-    pub suggestions: Vec<CodeSuggestion>,
+    pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
 
     /// This is not used for highlighting or rendering any error message.  Rather, it can be used
     /// as a sort key to sort a buffer of diagnostics.  By default, it is the primary span of
@@ -106,7 +111,7 @@ impl Diagnostic {
             code,
             span: MultiSpan::new(),
             children: vec![],
-            suggestions: vec![],
+            suggestions: Ok(vec![]),
             sort_span: DUMMY_SP,
             is_lint: false,
         }
@@ -300,6 +305,21 @@ impl Diagnostic {
         self
     }
 
+    /// Disallow attaching suggestions this diagnostic.
+    /// Any suggestions attached e.g. with the `span_suggestion_*` methods
+    /// (before and after the call to `disable_suggestions`) will be ignored.
+    pub fn disable_suggestions(&mut self) -> &mut Self {
+        self.suggestions = Err(SuggestionsDisabled);
+        self
+    }
+
+    /// Helper for pushing to `self.suggestions`, if available (not disable).
+    fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
+        if let Ok(suggestions) = &mut self.suggestions {
+            suggestions.push(suggestion);
+        }
+    }
+
     /// Show a suggestion that has multiple parts to it.
     /// In other words, multiple changes need to be applied as part of this suggestion.
     pub fn multipart_suggestion(
@@ -340,7 +360,7 @@ impl Diagnostic {
         style: SuggestionStyle,
     ) -> &mut Self {
         assert!(!suggestion.is_empty());
-        self.suggestions.push(CodeSuggestion {
+        self.push_suggestion(CodeSuggestion {
             substitutions: vec![Substitution {
                 parts: suggestion
                     .into_iter()
@@ -368,7 +388,7 @@ impl Diagnostic {
         applicability: Applicability,
     ) -> &mut Self {
         assert!(!suggestion.is_empty());
-        self.suggestions.push(CodeSuggestion {
+        self.push_suggestion(CodeSuggestion {
             substitutions: vec![Substitution {
                 parts: suggestion
                     .into_iter()
@@ -426,7 +446,7 @@ impl Diagnostic {
         applicability: Applicability,
         style: SuggestionStyle,
     ) -> &mut Self {
-        self.suggestions.push(CodeSuggestion {
+        self.push_suggestion(CodeSuggestion {
             substitutions: vec![Substitution {
                 parts: vec![SubstitutionPart { snippet: suggestion, span: sp }],
             }],
@@ -471,7 +491,7 @@ impl Diagnostic {
             .into_iter()
             .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
             .collect();
-        self.suggestions.push(CodeSuggestion {
+        self.push_suggestion(CodeSuggestion {
             substitutions,
             msg: msg.to_owned(),
             style: SuggestionStyle::ShowCode,
@@ -489,7 +509,7 @@ impl Diagnostic {
         suggestions: impl Iterator<Item = Vec<(Span, String)>>,
         applicability: Applicability,
     ) -> &mut Self {
-        self.suggestions.push(CodeSuggestion {
+        self.push_suggestion(CodeSuggestion {
             substitutions: suggestions
                 .map(|sugg| Substitution {
                     parts: sugg
@@ -578,7 +598,7 @@ impl Diagnostic {
         applicability: Applicability,
         tool_metadata: Json,
     ) {
-        self.suggestions.push(CodeSuggestion {
+        self.push_suggestion(CodeSuggestion {
             substitutions: vec![],
             msg: msg.to_owned(),
             style: SuggestionStyle::CompletelyHidden,
@@ -668,7 +688,7 @@ impl Diagnostic {
         &Vec<(String, Style)>,
         &Option<DiagnosticId>,
         &MultiSpan,
-        &Vec<CodeSuggestion>,
+        &Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
         Option<&Vec<SubDiagnostic>>,
     ) {
         (
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 6f84b0d400e..200c7cbccd9 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -22,12 +22,13 @@ pub struct DiagnosticBuilder<'a>(Box<DiagnosticBuilderInner<'a>>);
 /// (RVO) should avoid unnecessary copying. In practice, it does not (at the
 /// time of writing). The split between `DiagnosticBuilder` and
 /// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls.
+// FIXME(eddyb) try having two pointers in `DiagnosticBuilder`, by only boxing
+// `Diagnostic` (i.e. `struct DiagnosticBuilder(&Handler, Box<Diagnostic>);`).
 #[must_use]
 #[derive(Clone)]
 struct DiagnosticBuilderInner<'a> {
     handler: &'a Handler,
     diagnostic: Diagnostic,
-    allow_suggestions: bool,
 }
 
 /// In general, the `DiagnosticBuilder` uses deref to allow access to
@@ -244,164 +245,79 @@ impl<'a> DiagnosticBuilder<'a> {
     ) -> &mut Self);
     forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
 
-    /// See [`Diagnostic::multipart_suggestion()`].
-    pub fn multipart_suggestion(
+    forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
+
+    forward!(pub fn multipart_suggestion(
         &mut self,
         msg: &str,
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.multipart_suggestion(msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::multipart_suggestion()`].
-    pub fn multipart_suggestion_verbose(
+    ) -> &mut Self);
+    forward!(pub fn multipart_suggestion_verbose(
         &mut self,
         msg: &str,
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.multipart_suggestion_verbose(msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::tool_only_multipart_suggestion()`].
-    pub fn tool_only_multipart_suggestion(
+    ) -> &mut Self);
+    forward!(pub fn tool_only_multipart_suggestion(
         &mut self,
         msg: &str,
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.tool_only_multipart_suggestion(msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::span_suggestion()`].
-    pub fn span_suggestion(
+    ) -> &mut Self);
+    forward!(pub fn span_suggestion(
         &mut self,
         sp: Span,
         msg: &str,
         suggestion: String,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.span_suggestion(sp, msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::span_suggestions()`].
-    pub fn span_suggestions(
+    ) -> &mut Self);
+    forward!(pub fn span_suggestions(
         &mut self,
         sp: Span,
         msg: &str,
         suggestions: impl Iterator<Item = String>,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.span_suggestions(sp, msg, suggestions, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::multipart_suggestions()`].
-    pub fn multipart_suggestions(
+    ) -> &mut Self);
+    forward!(pub fn multipart_suggestions(
         &mut self,
         msg: &str,
         suggestions: impl Iterator<Item = Vec<(Span, String)>>,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::span_suggestion_short()`].
-    pub fn span_suggestion_short(
+    ) -> &mut Self);
+    forward!(pub fn span_suggestion_short(
         &mut self,
         sp: Span,
         msg: &str,
         suggestion: String,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.span_suggestion_short(sp, msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::span_suggestion_verbose()`].
-    pub fn span_suggestion_verbose(
+    ) -> &mut Self);
+    forward!(pub fn span_suggestion_verbose(
         &mut self,
         sp: Span,
         msg: &str,
         suggestion: String,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.span_suggestion_verbose(sp, msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::span_suggestion_hidden()`].
-    pub fn span_suggestion_hidden(
+    ) -> &mut Self);
+    forward!(pub fn span_suggestion_hidden(
         &mut self,
         sp: Span,
         msg: &str,
         suggestion: String,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.span_suggestion_hidden(sp, msg, suggestion, applicability);
-        self
-    }
-
-    /// See [`Diagnostic::tool_only_span_suggestion()`] for more information.
-    pub fn tool_only_span_suggestion(
+    ) -> &mut Self);
+    forward!(pub fn tool_only_span_suggestion(
         &mut self,
         sp: Span,
         msg: &str,
         suggestion: String,
         applicability: Applicability,
-    ) -> &mut Self {
-        if !self.0.allow_suggestions {
-            return self;
-        }
-        self.0.diagnostic.tool_only_span_suggestion(sp, msg, suggestion, applicability);
-        self
-    }
+    ) -> &mut Self);
 
     forward!(pub fn set_primary_message<M: Into<String>>(&mut self, msg: M) -> &mut Self);
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
     forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
-    /// Allow attaching suggestions this diagnostic.
-    /// If this is set to `false`, then any suggestions attached with the `span_suggestion_*`
-    /// methods after this is set to `false` will be ignored.
-    pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self {
-        self.0.allow_suggestions = allow;
-        self
-    }
-
     /// Convenience function for internal use, clients should use one of the
     /// `struct_*` methods on [`Handler`].
     crate fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
@@ -424,11 +340,7 @@ impl<'a> DiagnosticBuilder<'a> {
     /// diagnostic.
     crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
         debug!("Created new diagnostic");
-        DiagnosticBuilder(Box::new(DiagnosticBuilderInner {
-            handler,
-            diagnostic,
-            allow_suggestions: true,
-        }))
+        DiagnosticBuilder(Box::new(DiagnosticBuilderInner { handler, diagnostic }))
     }
 }
 
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 3104bc185e7..f90f4d46a9a 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -227,7 +227,8 @@ pub trait Emitter {
         diag: &'a Diagnostic,
     ) -> (MultiSpan, &'a [CodeSuggestion]) {
         let mut primary_span = diag.span.clone();
-        if let Some((sugg, rest)) = diag.suggestions.split_first() {
+        let suggestions = diag.suggestions.as_ref().map_or(&[][..], |suggestions| &suggestions[..]);
+        if let Some((sugg, rest)) = suggestions.split_first() {
             if rest.is_empty() &&
                // ^ if there is only one suggestion
                // don't display multi-suggestions as labels
@@ -282,10 +283,10 @@ pub trait Emitter {
                 // to be consistent. We could try to figure out if we can
                 // make one (or the first one) inline, but that would give
                 // undue importance to a semi-random suggestion
-                (primary_span, &diag.suggestions)
+                (primary_span, suggestions)
             }
         } else {
-            (primary_span, &diag.suggestions)
+            (primary_span, suggestions)
         }
     }
 
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index c2af2b2a86d..ff3478073d9 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -345,7 +345,7 @@ struct UnusedExterns<'a, 'b, 'c> {
 
 impl Diagnostic {
     fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
-        let sugg = diag.suggestions.iter().map(|sugg| Diagnostic {
+        let sugg = diag.suggestions.iter().flatten().map(|sugg| Diagnostic {
             message: sugg.msg.clone(),
             code: None,
             level: "help",