about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/early/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_lint/src/early/diagnostics.rs')
-rw-r--r--compiler/rustc_lint/src/early/diagnostics.rs467
1 files changed, 467 insertions, 0 deletions
diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs
new file mode 100644
index 00000000000..6d73715562b
--- /dev/null
+++ b/compiler/rustc_lint/src/early/diagnostics.rs
@@ -0,0 +1,467 @@
+#![allow(rustc::diagnostic_outside_of_impl)]
+#![allow(rustc::untranslatable_diagnostic)]
+
+use std::borrow::Cow;
+
+use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
+use rustc_errors::{
+    Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion,
+};
+use rustc_middle::middle::stability;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::Session;
+use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
+use rustc_span::{BytePos, kw};
+use tracing::debug;
+
+use crate::lints::{self, ElidedNamedLifetime};
+
+mod check_cfg;
+
+pub(super) fn decorate_lint(
+    sess: &Session,
+    tcx: Option<TyCtxt<'_>>,
+    diagnostic: BuiltinLintDiag,
+    diag: &mut Diag<'_, ()>,
+) {
+    match diagnostic {
+        BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => {
+            let spans: Vec<_> = content
+                .char_indices()
+                .filter_map(|(i, c)| {
+                    TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+                        let lo = comment_span.lo() + BytePos(2 + i as u32);
+                        (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+                    })
+                })
+                .collect();
+            let characters = spans
+                .iter()
+                .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") })
+                .collect();
+            let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion {
+                spans: spans.iter().map(|(_c, span)| *span).collect(),
+            });
+
+            lints::UnicodeTextFlow {
+                comment_span,
+                characters,
+                suggestions,
+                num_codepoints: spans.len(),
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::AbsPathWithModule(mod_span) => {
+            let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) {
+                Ok(ref s) => {
+                    // FIXME(Manishearth) ideally the emitting code
+                    // can tell us whether or not this is global
+                    let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
+
+                    (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
+                }
+                Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
+            };
+            lints::AbsPathWithModule {
+                sugg: lints::AbsPathWithModuleSugg { span: mod_span, applicability, replacement },
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => {
+            lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident }
+                .decorate_lint(diag)
+        }
+        BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
+            lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def }
+                .decorate_lint(diag)
+        }
+
+        BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
+            lints::ElidedLifetimesInPaths {
+                subdiag: elided_lifetime_in_path_suggestion(
+                    sess.source_map(),
+                    n,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_span,
+                ),
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
+            let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate });
+            lints::UnknownCrateTypes { sugg }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedImports {
+            remove_whole_use,
+            num_to_remove,
+            remove_spans,
+            test_module_span,
+            span_snippets,
+        } => {
+            let sugg = if remove_whole_use {
+                lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] }
+            } else {
+                lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove }
+            };
+            let test_module_span =
+                test_module_span.map(|span| sess.source_map().guess_head_span(span));
+
+            lints::UnusedImports {
+                sugg,
+                test_module_span,
+                num_snippets: span_snippets.len(),
+                span_snippets: DiagArgValue::StrListSepByAnd(
+                    span_snippets.into_iter().map(Cow::Owned).collect(),
+                ),
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::RedundantImport(spans, ident) => {
+            let subs = spans
+                .into_iter()
+                .map(|(span, is_imported)| {
+                    (match (span.is_dummy(), is_imported) {
+                        (false, true) => lints::RedundantImportSub::ImportedHere,
+                        (false, false) => lints::RedundantImportSub::DefinedHere,
+                        (true, true) => lints::RedundantImportSub::ImportedPrelude,
+                        (true, false) => lints::RedundantImportSub::DefinedPrelude,
+                    })(span)
+                })
+                .collect();
+            lints::RedundantImport { subs, ident }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::DeprecatedMacro {
+            suggestion,
+            suggestion_span,
+            note,
+            path,
+            since_kind,
+        } => {
+            let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion {
+                span: suggestion_span,
+                kind: "macro".to_owned(),
+                suggestion,
+            });
+
+            stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
+                .decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedDocComment(attr_span) => {
+            lints::UnusedDocComment { span: attr_span }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
+            let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
+            if is_foreign {
+                lints::PatternsInFnsWithoutBody::Foreign { sub }
+            } else {
+                lints::PatternsInFnsWithoutBody::Bodiless { sub }
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::MissingAbi(label_span, default_abi) => {
+            lints::MissingAbi { span: label_span, default_abi: default_abi.name() }
+                .decorate_lint(diag);
+        }
+        BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
+            lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
+            lints::OrPatternsBackCompat { span: suggestion_span, suggestion }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::ReservedPrefix(label_span, prefix) => {
+            lints::ReservedPrefix {
+                label: label_span,
+                suggestion: label_span.shrink_to_hi(),
+                prefix,
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::RawPrefix(label_span) => {
+            lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }
+                .decorate_lint(diag);
+        }
+        BuiltinLintDiag::ReservedString { is_string, suggestion } => {
+            if is_string {
+                lints::ReservedString { suggestion }.decorate_lint(diag);
+            } else {
+                lints::ReservedMultihash { suggestion }.decorate_lint(diag);
+            }
+        }
+        BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
+            lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
+            lints::TrailingMacro { is_trailing, name }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => {
+            lints::BreakWithLabelAndLoop {
+                sub: lints::BreakWithLabelAndLoopSub {
+                    left: sugg_span.shrink_to_lo(),
+                    right: sugg_span.shrink_to_hi(),
+                },
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnexpectedCfgName(name, value) => {
+            check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
+            check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag);
+        }
+        BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
+            let suggestion = match sugg {
+                Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd {
+                    left: left_sp,
+                    right: right_sp,
+                    sugg,
+                },
+                None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp },
+            };
+            lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => {
+            lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::SingleUseLifetime {
+            param_span,
+            use_span: Some((use_span, elide)),
+            deletion_span,
+            ident,
+        } => {
+            debug!(?param_span, ?use_span, ?deletion_span);
+            let suggestion = if let Some(deletion_span) = deletion_span {
+                let (use_span, replace_lt) = if elide {
+                    let use_span = sess.source_map().span_extend_while_whitespace(use_span);
+                    (use_span, String::new())
+                } else {
+                    (use_span, "'_".to_owned())
+                };
+                debug!(?deletion_span, ?use_span);
+
+                // issue 107998 for the case such as a wrong function pointer type
+                // `deletion_span` is empty and there is no need to report lifetime uses here
+                let deletion_span =
+                    if deletion_span.is_empty() { None } else { Some(deletion_span) };
+                Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt })
+            } else {
+                None
+            };
+
+            lints::SingleUseLifetime { suggestion, param_span, use_span, ident }
+                .decorate_lint(diag);
+        }
+        BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
+            debug!(?deletion_span);
+            lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::NamedArgumentUsedPositionally {
+            position_sp_to_replace,
+            position_sp_for_msg,
+            named_arg_sp,
+            named_arg_name,
+            is_formatting_arg,
+        } => {
+            let (suggestion, name) = if let Some(positional_arg_to_replace) = position_sp_to_replace
+            {
+                let mut name = named_arg_name.clone();
+                if is_formatting_arg {
+                    name.push('$')
+                };
+                let span_to_replace = if let Ok(positional_arg_content) =
+                    sess.source_map().span_to_snippet(positional_arg_to_replace)
+                    && positional_arg_content.starts_with(':')
+                {
+                    positional_arg_to_replace.shrink_to_lo()
+                } else {
+                    positional_arg_to_replace
+                };
+                (Some(span_to_replace), name)
+            } else {
+                (None, String::new())
+            };
+
+            lints::NamedArgumentUsedPositionally {
+                named_arg_sp,
+                position_label_sp: position_sp_for_msg,
+                suggestion,
+                name,
+                named_arg_name,
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
+            lints::ByteSliceInPackedStructWithDerive { ty }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedExternCrate { removal_span } => {
+            lints::UnusedExternCrate { removal_span }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
+            let suggestion_span = vis_span.between(ident_span);
+            let code = if vis_span.is_empty() { "use " } else { " use " };
+
+            lints::ExternCrateNotIdiomatic { span: suggestion_span, code }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
+            lints::AmbiguousGlobImports { ambiguity }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::AmbiguousGlobReexports {
+            name,
+            namespace,
+            first_reexport_span,
+            duplicate_reexport_span,
+        } => {
+            lints::AmbiguousGlobReexports {
+                first_reexport: first_reexport_span,
+                duplicate_reexport: duplicate_reexport_span,
+                name,
+                namespace,
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::HiddenGlobReexports {
+            name,
+            namespace,
+            glob_reexport_span,
+            private_item_span,
+        } => {
+            lints::HiddenGlobReexports {
+                glob_reexport: glob_reexport_span,
+                private_item: private_item_span,
+
+                name,
+                namespace,
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedQualifications { removal_span } => {
+            lints::UnusedQualifications { removal_span }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
+            attribute_name_span,
+            sugg_spans: (left, right),
+        } => {
+            lints::UnsafeAttrOutsideUnsafe {
+                span: attribute_name_span,
+                suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::AssociatedConstElidedLifetime {
+            elided,
+            span: lt_span,
+            lifetimes_in_scope,
+        } => {
+            let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
+            let code = if elided { "'static " } else { "'static" };
+            lints::AssociatedConstElidedLifetime {
+                span: lt_span,
+                code,
+                elided,
+                lifetimes_in_scope,
+            }
+            .decorate_lint(diag);
+        }
+        BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => {
+            lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis }
+                .decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnknownDiagnosticAttribute { span: typo_span, typo_name } => {
+            let typo = typo_name.map(|typo_name| lints::UnknownDiagnosticAttributeTypoSugg {
+                span: typo_span,
+                typo_name,
+            });
+            lints::UnknownDiagnosticAttribute { typo }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::MacroUseDeprecated => {
+            lints::MacroUseDeprecated.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedMacroUse => lints::UnusedMacroUse.decorate_lint(diag),
+        BuiltinLintDiag::PrivateExternCrateReexport { source: ident, extern_crate_span } => {
+            lints::PrivateExternCrateReexport { ident, sugg: extern_crate_span.shrink_to_lo() }
+                .decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedLabel => lints::UnusedLabel.decorate_lint(diag),
+        BuiltinLintDiag::MacroIsPrivate(ident) => {
+            lints::MacroIsPrivate { ident }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedMacroDefinition(name) => {
+            lints::UnusedMacroDefinition { name }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::MacroRuleNeverUsed(n, name) => {
+            lints::MacroRuleNeverUsed { n: n + 1, name }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnstableFeature(msg) => {
+            lints::UnstableFeature { msg }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::AvoidUsingIntelSyntax => {
+            lints::AvoidIntelSyntax.decorate_lint(diag);
+        }
+        BuiltinLintDiag::AvoidUsingAttSyntax => {
+            lints::AvoidAttSyntax.decorate_lint(diag);
+        }
+        BuiltinLintDiag::IncompleteInclude => {
+            lints::IncompleteInclude.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnnameableTestItems => {
+            lints::UnnameableTestItems.decorate_lint(diag);
+        }
+        BuiltinLintDiag::DuplicateMacroAttribute => {
+            lints::DuplicateMacroAttribute.decorate_lint(diag);
+        }
+        BuiltinLintDiag::CfgAttrNoAttributes => {
+            lints::CfgAttrNoAttributes.decorate_lint(diag);
+        }
+        BuiltinLintDiag::MissingFragmentSpecifier => {
+            lints::MissingFragmentSpecifier.decorate_lint(diag);
+        }
+        BuiltinLintDiag::MetaVariableStillRepeating(name) => {
+            lints::MetaVariableStillRepeating { name }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::MetaVariableWrongOperator => {
+            lints::MetaVariableWrongOperator.decorate_lint(diag);
+        }
+        BuiltinLintDiag::DuplicateMatcherBinding => {
+            lints::DuplicateMatcherBinding.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnknownMacroVariable(name) => {
+            lints::UnknownMacroVariable { name }.decorate_lint(diag);
+        }
+        BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
+            lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
+        }
+        BuiltinLintDiag::WasmCAbi => lints::WasmCAbi.decorate_lint(diag),
+        BuiltinLintDiag::IllFormedAttributeInput { suggestions } => {
+            lints::IllFormedAttributeInput {
+                num_suggestions: suggestions.len(),
+                suggestions: DiagArgValue::StrListSepByAnd(
+                    suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
+                ),
+            }
+            .decorate_lint(diag)
+        }
+        BuiltinLintDiag::InnerAttributeUnstable { is_macro } => if is_macro {
+            lints::InnerAttributeUnstable::InnerMacroAttribute
+        } else {
+            lints::InnerAttributeUnstable::CustomInnerAttribute
+        }
+        .decorate_lint(diag),
+        BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
+            lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
+        }
+        BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
+            lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
+        }
+        BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => {
+            match resolution {
+                ElidedLifetimeResolution::Static => {
+                    ElidedNamedLifetime { span, kind, name: kw::StaticLifetime, declaration: None }
+                }
+                ElidedLifetimeResolution::Param(name, declaration) => {
+                    ElidedNamedLifetime { span, kind, name, declaration: Some(declaration) }
+                }
+            }
+            .decorate_lint(diag)
+        }
+    }
+}