1 use crate::snippet
::Style
;
3 CodeSuggestion
, DiagnosticMessage
, Level
, MultiSpan
, SubdiagnosticMessage
, Substitution
,
4 SubstitutionPart
, SuggestionStyle
,
6 use rustc_data_structures
::stable_map
::FxHashMap
;
7 use rustc_error_messages
::FluentValue
;
8 use rustc_lint_defs
::{Applicability, LintExpectationId}
;
9 use rustc_span
::edition
::LATEST_STABLE_EDITION
;
10 use rustc_span
::symbol
::{Ident, Symbol}
;
11 use rustc_span
::{Span, DUMMY_SP}
;
14 use std
::hash
::{Hash, Hasher}
;
16 /// Error type for `Diagnostic`'s `suggestions` field, indicating that
17 /// `.disable_suggestions()` was called on the `Diagnostic`.
18 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
19 pub struct SuggestionsDisabled
;
21 /// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
22 /// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of
23 /// diagnostic emission.
24 pub type DiagnosticArg
<'source
> = (Cow
<'source
, str>, DiagnosticArgValue
<'source
>);
26 /// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
27 /// to a `FluentValue` by the emitter to be used in diagnostic translation.
28 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
29 pub enum DiagnosticArgValue
<'source
> {
30 Str(Cow
<'source
, str>),
34 /// Converts a value of a type into a `DiagnosticArg` (typically a field of a `SessionDiagnostic`
35 /// struct). Implemented as a custom trait rather than `From` so that it is implemented on the type
36 /// being converted rather than on `DiagnosticArgValue`, which enables types from other `rustc_*`
37 /// crates to implement this.
38 pub trait IntoDiagnosticArg
{
39 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static>;
42 impl IntoDiagnosticArg
for String
{
43 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static> {
44 DiagnosticArgValue
::Str(Cow
::Owned(self))
48 impl IntoDiagnosticArg
for Symbol
{
49 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static> {
50 self.to_ident_string().into_diagnostic_arg()
54 impl IntoDiagnosticArg
for Ident
{
55 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static> {
56 self.to_string().into_diagnostic_arg()
60 impl<'a
> IntoDiagnosticArg
for &'a
str {
61 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static> {
62 self.to_string().into_diagnostic_arg()
66 impl IntoDiagnosticArg
for usize {
67 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static> {
68 DiagnosticArgValue
::Number(self)
72 impl<'source
> Into
<FluentValue
<'source
>> for DiagnosticArgValue
<'source
> {
73 fn into(self) -> FluentValue
<'source
> {
75 DiagnosticArgValue
::Str(s
) => From
::from(s
),
76 DiagnosticArgValue
::Number(n
) => From
::from(n
),
81 /// Trait implemented by error types. This should not be implemented manually. Instead, use
82 /// `#[derive(SessionSubdiagnostic)]` -- see [rustc_macros::SessionSubdiagnostic].
83 #[rustc_diagnostic_item = "AddSubdiagnostic"]
84 pub trait AddSubdiagnostic
{
85 /// Add a subdiagnostic to an existing diagnostic.
86 fn add_to_diagnostic(self, diag
: &mut Diagnostic
);
90 #[derive(Clone, Debug, Encodable, Decodable)]
91 pub struct Diagnostic
{
92 // NOTE(eddyb) this is private to disallow arbitrary after-the-fact changes,
93 // outside of what methods in this crate themselves allow.
94 pub(crate) level
: Level
,
96 pub message
: Vec
<(DiagnosticMessage
, Style
)>,
97 pub code
: Option
<DiagnosticId
>,
99 pub children
: Vec
<SubDiagnostic
>,
100 pub suggestions
: Result
<Vec
<CodeSuggestion
>, SuggestionsDisabled
>,
101 args
: Vec
<DiagnosticArg
<'
static>>,
103 /// This is not used for highlighting or rendering any error message. Rather, it can be used
104 /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
105 /// `span` if there is one. Otherwise, it is `DUMMY_SP`.
108 /// If diagnostic is from Lint, custom hash function ignores notes
109 /// otherwise hash is based on the all the fields
113 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
114 pub enum DiagnosticId
{
116 Lint { name: String, has_future_breakage: bool, is_force_warn: bool }
,
119 /// A "sub"-diagnostic attached to a parent diagnostic.
120 /// For example, a note attached to an error.
121 #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
122 pub struct SubDiagnostic
{
124 pub message
: Vec
<(DiagnosticMessage
, Style
)>,
126 pub render_span
: Option
<MultiSpan
>,
129 #[derive(Debug, PartialEq, Eq)]
130 pub struct DiagnosticStyledString(pub Vec
<StringPart
>);
132 impl DiagnosticStyledString
{
133 pub fn new() -> DiagnosticStyledString
{
134 DiagnosticStyledString(vec
![])
136 pub fn push_normal
<S
: Into
<String
>>(&mut self, t
: S
) {
137 self.0.push(StringPart
::Normal(t
.into()));
139 pub fn push_highlighted
<S
: Into
<String
>>(&mut self, t
: S
) {
140 self.0.push(StringPart
::Highlighted(t
.into()));
142 pub fn push
<S
: Into
<String
>>(&mut self, t
: S
, highlight
: bool
) {
144 self.push_highlighted(t
);
149 pub fn normal
<S
: Into
<String
>>(t
: S
) -> DiagnosticStyledString
{
150 DiagnosticStyledString(vec
![StringPart
::Normal(t
.into())])
153 pub fn highlighted
<S
: Into
<String
>>(t
: S
) -> DiagnosticStyledString
{
154 DiagnosticStyledString(vec
![StringPart
::Highlighted(t
.into())])
157 pub fn content(&self) -> String
{
158 self.0.iter
().map(|x
| x
.content()).collect
::<String
>()
162 #[derive(Debug, PartialEq, Eq)]
163 pub enum StringPart
{
169 pub fn content(&self) -> &str {
171 &StringPart
::Normal(ref s
) | &StringPart
::Highlighted(ref s
) => s
,
177 pub fn new
<M
: Into
<DiagnosticMessage
>>(level
: Level
, message
: M
) -> Self {
178 Diagnostic
::new_with_code(level
, None
, message
)
181 pub fn new_with_code
<M
: Into
<DiagnosticMessage
>>(
183 code
: Option
<DiagnosticId
>,
188 message
: vec
![(message
.into(), Style
::NoStyle
)],
190 span
: MultiSpan
::new(),
192 suggestions
: Ok(vec
![]),
200 pub fn level(&self) -> Level
{
204 pub fn is_error(&self) -> bool
{
209 | Level
::Error { .. }
210 | Level
::FailureNote
=> true,
217 | Level
::Expect(_
) => false,
221 pub fn update_unstable_expectation_id(
223 unstable_to_stable
: &FxHashMap
<LintExpectationId
, LintExpectationId
>,
225 if let Level
::Expect(expectation_id
) | Level
::Warning(Some(expectation_id
)) =
228 if expectation_id
.is_stable() {
232 // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index.
233 // The lint index inside the attribute is manually transferred here.
234 let lint_index
= expectation_id
.get_lint_index();
235 expectation_id
.set_lint_index(None
);
236 let mut stable_id
= *unstable_to_stable
237 .get(&expectation_id
)
238 .expect("each unstable `LintExpectationId` must have a matching stable id");
240 stable_id
.set_lint_index(lint_index
);
241 *expectation_id
= stable_id
;
245 pub fn has_future_breakage(&self) -> bool
{
247 Some(DiagnosticId
::Lint { has_future_breakage, .. }
) => has_future_breakage
,
252 pub fn is_force_warn(&self) -> bool
{
254 Some(DiagnosticId
::Lint { is_force_warn, .. }
) => is_force_warn
,
259 /// Delay emission of this diagnostic as a bug.
261 /// This can be useful in contexts where an error indicates a bug but
262 /// typically this only happens when other compilation errors have already
263 /// happened. In those cases this can be used to defer emission of this
264 /// diagnostic as a bug in the compiler only if no other errors have been
267 /// In the meantime, though, callsites are required to deal with the "bug"
268 /// locally in whichever way makes the most sense.
270 pub fn downgrade_to_delayed_bug(&mut self) -> &mut Self {
273 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
276 self.level
= Level
::DelayedBug
;
281 /// Adds a span/label to be included in the resulting snippet.
283 /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic
284 /// was first built. That means it will be shown together with the original
285 /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods.
287 /// This span is *not* considered a ["primary span"][`MultiSpan`]; only
288 /// the `Span` supplied when creating the diagnostic is primary.
289 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
290 pub fn span_label(&mut self, span
: Span
, label
: impl Into
<SubdiagnosticMessage
>) -> &mut Self {
291 self.span
.push_span_label(span
, self.subdiagnostic_message_to_diagnostic_message(label
));
295 /// Labels all the given spans with the provided label.
296 /// See [`Self::span_label()`] for more information.
299 spans
: impl IntoIterator
<Item
= Span
>,
300 label
: impl AsRef
<str>,
302 let label
= label
.as_ref();
304 self.span_label(span
, label
);
309 pub fn replace_span_with(&mut self, after
: Span
) -> &mut Self {
310 let before
= self.span
.clone();
311 self.set_span(after
);
312 for span_label
in before
.span_labels() {
313 if let Some(label
) = span_label
.label
{
314 self.span
.push_span_label(after
, label
);
320 pub fn note_expected_found(
322 expected_label
: &dyn fmt
::Display
,
323 expected
: DiagnosticStyledString
,
324 found_label
: &dyn fmt
::Display
,
325 found
: DiagnosticStyledString
,
327 self.note_expected_found_extra(expected_label
, expected
, found_label
, found
, &"", &"")
330 pub fn note_unsuccessful_coercion(
332 expected
: DiagnosticStyledString
,
333 found
: DiagnosticStyledString
,
335 let mut msg
: Vec
<_
> =
336 vec
![("required when trying to coerce from type `".to_string(), Style
::NoStyle
)];
337 msg
.extend(expected
.0.iter
().map(|x
| match *x
{
338 StringPart
::Normal(ref s
) => (s
.to_owned(), Style
::NoStyle
),
339 StringPart
::Highlighted(ref s
) => (s
.to_owned(), Style
::Highlight
),
341 msg
.push(("` to type '".to_string(), Style
::NoStyle
));
342 msg
.extend(found
.0.iter
().map(|x
| match *x
{
343 StringPart
::Normal(ref s
) => (s
.to_owned(), Style
::NoStyle
),
344 StringPart
::Highlighted(ref s
) => (s
.to_owned(), Style
::Highlight
),
346 msg
.push(("`".to_string(), Style
::NoStyle
));
348 // For now, just attach these as notes
349 self.highlighted_note(msg
);
353 pub fn note_expected_found_extra(
355 expected_label
: &dyn fmt
::Display
,
356 expected
: DiagnosticStyledString
,
357 found_label
: &dyn fmt
::Display
,
358 found
: DiagnosticStyledString
,
359 expected_extra
: &dyn fmt
::Display
,
360 found_extra
: &dyn fmt
::Display
,
362 let expected_label
= expected_label
.to_string();
363 let expected_label
= if expected_label
.is_empty() {
364 "expected".to_string()
366 format
!("expected {}", expected_label
)
368 let found_label
= found_label
.to_string();
369 let found_label
= if found_label
.is_empty() {
372 format
!("found {}", found_label
)
374 let (found_padding
, expected_padding
) = if expected_label
.len() > found_label
.len() {
375 (expected_label
.len() - found_label
.len(), 0)
377 (0, found_label
.len() - expected_label
.len())
379 let mut msg
: Vec
<_
> =
380 vec
![(format
!("{}{} `", " ".repeat(expected_padding
), expected_label
), Style
::NoStyle
)];
381 msg
.extend(expected
.0.iter
().map(|x
| match *x
{
382 StringPart
::Normal(ref s
) => (s
.to_owned(), Style
::NoStyle
),
383 StringPart
::Highlighted(ref s
) => (s
.to_owned(), Style
::Highlight
),
385 msg
.push((format
!("`{}\n", expected_extra
), Style
::NoStyle
));
386 msg
.push((format
!("{}{} `", " ".repeat(found_padding
), found_label
), Style
::NoStyle
));
387 msg
.extend(found
.0.iter
().map(|x
| match *x
{
388 StringPart
::Normal(ref s
) => (s
.to_owned(), Style
::NoStyle
),
389 StringPart
::Highlighted(ref s
) => (s
.to_owned(), Style
::Highlight
),
391 msg
.push((format
!("`{}", found_extra
), Style
::NoStyle
));
393 // For now, just attach these as notes.
394 self.highlighted_note(msg
);
398 pub fn note_trait_signature(&mut self, name
: String
, signature
: String
) -> &mut Self {
399 self.highlighted_note(vec
![
400 (format
!("`{}` from trait: `", name
), Style
::NoStyle
),
401 (signature
, Style
::Highlight
),
402 ("`".to_string(), Style
::NoStyle
),
407 /// Add a note attached to this diagnostic.
408 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
409 pub fn note(&mut self, msg
: impl Into
<SubdiagnosticMessage
>) -> &mut Self {
410 self.sub(Level
::Note
, msg
, MultiSpan
::new(), None
);
414 pub fn highlighted_note
<M
: Into
<SubdiagnosticMessage
>>(
416 msg
: Vec
<(M
, Style
)>,
418 self.sub_with_highlights(Level
::Note
, msg
, MultiSpan
::new(), None
);
422 /// Prints the span with a note above it.
423 /// This is like [`Diagnostic::note()`], but it gets its own span.
424 pub fn note_once(&mut self, msg
: impl Into
<SubdiagnosticMessage
>) -> &mut Self {
425 self.sub(Level
::OnceNote
, msg
, MultiSpan
::new(), None
);
429 /// Prints the span with a note above it.
430 /// This is like [`Diagnostic::note()`], but it gets its own span.
431 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
432 pub fn span_note
<S
: Into
<MultiSpan
>>(
435 msg
: impl Into
<SubdiagnosticMessage
>,
437 self.sub(Level
::Note
, msg
, sp
.into(), None
);
441 /// Prints the span with a note above it.
442 /// This is like [`Diagnostic::note()`], but it gets its own span.
443 pub fn span_note_once
<S
: Into
<MultiSpan
>>(
446 msg
: impl Into
<SubdiagnosticMessage
>,
448 self.sub(Level
::OnceNote
, msg
, sp
.into(), None
);
452 /// Add a warning attached to this diagnostic.
453 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
454 pub fn warn(&mut self, msg
: impl Into
<SubdiagnosticMessage
>) -> &mut Self {
455 self.sub(Level
::Warning(None
), msg
, MultiSpan
::new(), None
);
459 /// Prints the span with a warning above it.
460 /// This is like [`Diagnostic::warn()`], but it gets its own span.
461 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
462 pub fn span_warn
<S
: Into
<MultiSpan
>>(
465 msg
: impl Into
<SubdiagnosticMessage
>,
467 self.sub(Level
::Warning(None
), msg
, sp
.into(), None
);
471 /// Add a help message attached to this diagnostic.
472 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
473 pub fn help(&mut self, msg
: impl Into
<SubdiagnosticMessage
>) -> &mut Self {
474 self.sub(Level
::Help
, msg
, MultiSpan
::new(), None
);
478 /// Add a help message attached to this diagnostic with a customizable highlighted message.
479 pub fn highlighted_help(&mut self, msg
: Vec
<(String
, Style
)>) -> &mut Self {
480 self.sub_with_highlights(Level
::Help
, msg
, MultiSpan
::new(), None
);
484 /// Prints the span with some help above it.
485 /// This is like [`Diagnostic::help()`], but it gets its own span.
486 #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
487 pub fn span_help
<S
: Into
<MultiSpan
>>(
490 msg
: impl Into
<SubdiagnosticMessage
>,
492 self.sub(Level
::Help
, msg
, sp
.into(), None
);
496 /// Help the user upgrade to the latest edition.
497 /// This is factored out to make sure it does the right thing with `Cargo.toml`.
498 pub fn help_use_latest_edition(&mut self) -> &mut Self {
499 if std
::env
::var_os("CARGO").is_some() {
500 self.help(&format
!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION
));
502 self.help(&format
!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION
));
504 self.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
508 /// Disallow attaching suggestions this diagnostic.
509 /// Any suggestions attached e.g. with the `span_suggestion_*` methods
510 /// (before and after the call to `disable_suggestions`) will be ignored.
511 pub fn disable_suggestions(&mut self) -> &mut Self {
512 self.suggestions
= Err(SuggestionsDisabled
);
516 /// Helper for pushing to `self.suggestions`, if available (not disable).
517 fn push_suggestion(&mut self, suggestion
: CodeSuggestion
) {
518 if let Ok(suggestions
) = &mut self.suggestions
{
519 suggestions
.push(suggestion
);
523 /// Show a suggestion that has multiple parts to it.
524 /// In other words, multiple changes need to be applied as part of this suggestion.
525 pub fn multipart_suggestion(
527 msg
: impl Into
<SubdiagnosticMessage
>,
528 suggestion
: Vec
<(Span
, String
)>,
529 applicability
: Applicability
,
531 self.multipart_suggestion_with_style(
535 SuggestionStyle
::ShowCode
,
539 /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic.
540 /// In other words, multiple changes need to be applied as part of this suggestion.
541 pub fn multipart_suggestion_verbose(
543 msg
: impl Into
<SubdiagnosticMessage
>,
544 suggestion
: Vec
<(Span
, String
)>,
545 applicability
: Applicability
,
547 self.multipart_suggestion_with_style(
551 SuggestionStyle
::ShowAlways
,
554 /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
555 pub fn multipart_suggestion_with_style(
557 msg
: impl Into
<SubdiagnosticMessage
>,
558 suggestion
: Vec
<(Span
, String
)>,
559 applicability
: Applicability
,
560 style
: SuggestionStyle
,
562 assert
!(!suggestion
.is_empty());
563 self.push_suggestion(CodeSuggestion
{
564 substitutions
: vec
![Substitution
{
567 .map(|(span
, snippet
)| SubstitutionPart { snippet, span }
)
570 msg
: self.subdiagnostic_message_to_diagnostic_message(msg
),
577 /// Prints out a message with for a multipart suggestion without showing the suggested code.
579 /// This is intended to be used for suggestions that are obvious in what the changes need to
580 /// be from the message, showing the span label inline would be visually unpleasant
581 /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
582 /// improve understandability.
583 pub fn tool_only_multipart_suggestion(
585 msg
: impl Into
<SubdiagnosticMessage
>,
586 suggestion
: Vec
<(Span
, String
)>,
587 applicability
: Applicability
,
589 assert
!(!suggestion
.is_empty());
590 self.push_suggestion(CodeSuggestion
{
591 substitutions
: vec
![Substitution
{
594 .map(|(span
, snippet
)| SubstitutionPart { snippet, span }
)
597 msg
: self.subdiagnostic_message_to_diagnostic_message(msg
),
598 style
: SuggestionStyle
::CompletelyHidden
,
604 /// Prints out a message with a suggested edit of the code.
606 /// In case of short messages and a simple suggestion, rustc displays it as a label:
609 /// try adding parentheses: `(tup.0).1`
614 /// * should not end in any punctuation (a `:` is added automatically)
615 /// * should not be a question (avoid language like "did you mean")
616 /// * should not contain any phrases like "the following", "as shown", etc.
617 /// * may look like "to do xyz, use" or "to do xyz, use abc"
618 /// * may contain a name of a function, variable, or type, but not whole expressions
620 /// See `CodeSuggestion` for more information.
621 pub fn span_suggestion(
624 msg
: impl Into
<SubdiagnosticMessage
>,
625 suggestion
: impl ToString
,
626 applicability
: Applicability
,
628 self.span_suggestion_with_style(
633 SuggestionStyle
::ShowCode
,
638 /// [`Diagnostic::span_suggestion()`] but you can set the [`SuggestionStyle`].
639 pub fn span_suggestion_with_style(
642 msg
: impl Into
<SubdiagnosticMessage
>,
643 suggestion
: impl ToString
,
644 applicability
: Applicability
,
645 style
: SuggestionStyle
,
647 self.push_suggestion(CodeSuggestion
{
648 substitutions
: vec
![Substitution
{
649 parts
: vec
![SubstitutionPart { snippet: suggestion.to_string(), span: sp }
],
651 msg
: self.subdiagnostic_message_to_diagnostic_message(msg
),
658 /// Always show the suggested change.
659 pub fn span_suggestion_verbose(
662 msg
: impl Into
<SubdiagnosticMessage
>,
663 suggestion
: impl ToString
,
664 applicability
: Applicability
,
666 self.span_suggestion_with_style(
671 SuggestionStyle
::ShowAlways
,
676 /// Prints out a message with multiple suggested edits of the code.
677 /// See also [`Diagnostic::span_suggestion()`].
678 pub fn span_suggestions(
681 msg
: impl Into
<SubdiagnosticMessage
>,
682 suggestions
: impl Iterator
<Item
= String
>,
683 applicability
: Applicability
,
685 let mut suggestions
: Vec
<_
> = suggestions
.collect();
687 let substitutions
= suggestions
689 .map(|snippet
| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }
] })
691 self.push_suggestion(CodeSuggestion
{
693 msg
: self.subdiagnostic_message_to_diagnostic_message(msg
),
694 style
: SuggestionStyle
::ShowCode
,
700 /// Prints out a message with multiple suggested edits of the code.
701 /// See also [`Diagnostic::span_suggestion()`].
702 pub fn multipart_suggestions(
704 msg
: impl Into
<SubdiagnosticMessage
>,
705 suggestions
: impl Iterator
<Item
= Vec
<(Span
, String
)>>,
706 applicability
: Applicability
,
708 self.push_suggestion(CodeSuggestion
{
709 substitutions
: suggestions
710 .map(|sugg
| Substitution
{
713 .map(|(span
, snippet
)| SubstitutionPart { snippet, span }
)
717 msg
: self.subdiagnostic_message_to_diagnostic_message(msg
),
718 style
: SuggestionStyle
::ShowCode
,
723 /// Prints out a message with a suggested edit of the code. If the suggestion is presented
724 /// inline, it will only show the message and not the suggestion.
726 /// See `CodeSuggestion` for more information.
727 pub fn span_suggestion_short(
730 msg
: impl Into
<SubdiagnosticMessage
>,
731 suggestion
: impl ToString
,
732 applicability
: Applicability
,
734 self.span_suggestion_with_style(
739 SuggestionStyle
::HideCodeInline
,
744 /// Prints out a message for a suggestion without showing the suggested code.
746 /// This is intended to be used for suggestions that are obvious in what the changes need to
747 /// be from the message, showing the span label inline would be visually unpleasant
748 /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
749 /// improve understandability.
750 pub fn span_suggestion_hidden(
753 msg
: impl Into
<SubdiagnosticMessage
>,
754 suggestion
: impl ToString
,
755 applicability
: Applicability
,
757 self.span_suggestion_with_style(
762 SuggestionStyle
::HideCodeAlways
,
767 /// Adds a suggestion to the JSON output that will not be shown in the CLI.
769 /// This is intended to be used for suggestions that are *very* obvious in what the changes
770 /// need to be from the message, but we still want other tools to be able to apply them.
771 pub fn tool_only_span_suggestion(
774 msg
: impl Into
<SubdiagnosticMessage
>,
775 suggestion
: impl ToString
,
776 applicability
: Applicability
,
778 self.span_suggestion_with_style(
783 SuggestionStyle
::CompletelyHidden
,
788 /// Add a subdiagnostic from a type that implements `SessionSubdiagnostic` - see
789 /// [rustc_macros::SessionSubdiagnostic].
790 pub fn subdiagnostic(&mut self, subdiagnostic
: impl AddSubdiagnostic
) -> &mut Self {
791 subdiagnostic
.add_to_diagnostic(self);
795 pub fn set_span
<S
: Into
<MultiSpan
>>(&mut self, sp
: S
) -> &mut Self {
796 self.span
= sp
.into();
797 if let Some(span
) = self.span
.primary_span() {
798 self.sort_span
= span
;
803 pub fn set_is_lint(&mut self) -> &mut Self {
808 pub fn code(&mut self, s
: DiagnosticId
) -> &mut Self {
813 pub fn clear_code(&mut self) -> &mut Self {
818 pub fn get_code(&self) -> Option
<DiagnosticId
> {
822 pub fn set_primary_message(&mut self, msg
: impl Into
<DiagnosticMessage
>) -> &mut Self {
823 self.message
[0] = (msg
.into(), Style
::NoStyle
);
827 pub fn args(&self) -> &[DiagnosticArg
<'
static>] {
833 name
: impl Into
<Cow
<'
static, str>>,
834 arg
: impl IntoDiagnosticArg
,
836 self.args
.push((name
.into(), arg
.into_diagnostic_arg()));
840 pub fn styled_message(&self) -> &[(DiagnosticMessage
, Style
)] {
844 /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
845 /// combining it with the primary message of the diagnostic (if translatable, otherwise it just
846 /// passes the user's string along).
847 fn subdiagnostic_message_to_diagnostic_message(
849 attr
: impl Into
<SubdiagnosticMessage
>,
850 ) -> DiagnosticMessage
{
852 self.message
.iter().map(|(msg
, _
)| msg
).next().expect("diagnostic with no messages");
853 msg
.with_subdiagnostic_message(attr
.into())
856 /// Convenience function for internal use, clients should use one of the
857 /// public methods above.
859 /// Used by `proc_macro_server` for implementing `server::Diagnostic`.
863 message
: impl Into
<SubdiagnosticMessage
>,
865 render_span
: Option
<MultiSpan
>,
867 let sub
= SubDiagnostic
{
870 self.subdiagnostic_message_to_diagnostic_message(message
),
876 self.children
.push(sub
);
879 /// Convenience function for internal use, clients should use one of the
880 /// public methods above.
881 fn sub_with_highlights
<M
: Into
<SubdiagnosticMessage
>>(
884 mut message
: Vec
<(M
, Style
)>,
886 render_span
: Option
<MultiSpan
>,
888 let message
= message
890 .map(|m
| (self.subdiagnostic_message_to_diagnostic_message(m
.0), m
.1))
892 let sub
= SubDiagnostic { level, message, span, render_span }
;
893 self.children
.push(sub
);
896 /// Fields used for Hash, and PartialEq trait
901 &[(DiagnosticMessage
, Style
)],
902 &Option
<DiagnosticId
>,
904 &Result
<Vec
<CodeSuggestion
>, SuggestionsDisabled
>,
905 Option
<&[SubDiagnostic
]>,
913 (if self.is_lint { None }
else { Some(&self.children) }
),
918 impl Hash
for Diagnostic
{
919 fn hash
<H
>(&self, state
: &mut H
)
923 self.keys().hash(state
);
927 impl PartialEq
for Diagnostic
{
928 fn eq(&self, other
: &Self) -> bool
{
929 self.keys() == other
.keys()