@@ -20,13 +20,14 @@ use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
2020use crate :: lint:: levels:: { LintLevelSets , LintLevelsBuilder } ;
2121use crate :: lint:: { EarlyLintPassObject , LateLintPassObject } ;
2222use crate :: middle:: privacy:: AccessLevels ;
23+ use crate :: middle:: stability;
2324use crate :: session:: Session ;
2425use crate :: ty:: layout:: { LayoutError , LayoutOf , TyLayout } ;
2526use crate :: ty:: { self , print:: Printer , subst:: GenericArg , Ty , TyCtxt } ;
2627use rustc_data_structures:: fx:: FxHashMap ;
2728use rustc_data_structures:: sync;
2829use rustc_error_codes:: * ;
29- use rustc_errors:: { struct_span_err, DiagnosticBuilder } ;
30+ use rustc_errors:: { pluralize , struct_span_err, Applicability , DiagnosticBuilder } ;
3031use rustc_hir as hir;
3132use rustc_hir:: def_id:: { CrateNum , DefId } ;
3233use rustc_session:: lint:: BuiltinLintDiagnostics ;
@@ -466,6 +467,48 @@ impl LintPassObject for EarlyLintPassObject {}
466467
467468impl LintPassObject for LateLintPassObject { }
468469
470+ pub fn add_elided_lifetime_in_path_suggestion (
471+ sess : & Session ,
472+ db : & mut DiagnosticBuilder < ' _ > ,
473+ n : usize ,
474+ path_span : Span ,
475+ incl_angl_brckt : bool ,
476+ insertion_span : Span ,
477+ anon_lts : String ,
478+ ) {
479+ let ( replace_span, suggestion) = if incl_angl_brckt {
480+ ( insertion_span, anon_lts)
481+ } else {
482+ // When possible, prefer a suggestion that replaces the whole
483+ // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
484+ // at a point (which makes for an ugly/confusing label)
485+ if let Ok ( snippet) = sess. source_map ( ) . span_to_snippet ( path_span) {
486+ // But our spans can get out of whack due to macros; if the place we think
487+ // we want to insert `'_` isn't even within the path expression's span, we
488+ // should bail out of making any suggestion rather than panicking on a
489+ // subtract-with-overflow or string-slice-out-out-bounds (!)
490+ // FIXME: can we do better?
491+ if insertion_span. lo ( ) . 0 < path_span. lo ( ) . 0 {
492+ return ;
493+ }
494+ let insertion_index = ( insertion_span. lo ( ) . 0 - path_span. lo ( ) . 0 ) as usize ;
495+ if insertion_index > snippet. len ( ) {
496+ return ;
497+ }
498+ let ( before, after) = snippet. split_at ( insertion_index) ;
499+ ( path_span, format ! ( "{}{}{}" , before, anon_lts, after) )
500+ } else {
501+ ( insertion_span, anon_lts)
502+ }
503+ } ;
504+ db. span_suggestion (
505+ replace_span,
506+ & format ! ( "indicate the anonymous lifetime{}" , pluralize!( n) ) ,
507+ suggestion,
508+ Applicability :: MachineApplicable ,
509+ ) ;
510+ }
511+
469512pub trait LintContext : Sized {
470513 type PassObject : LintPassObject ;
471514
@@ -484,7 +527,85 @@ pub trait LintContext: Sized {
484527 diagnostic : BuiltinLintDiagnostics ,
485528 ) {
486529 let mut db = self . lookup ( lint, span, msg) ;
487- super :: builtin:: run_builtin_lint_diagnostics ( diagnostic, self . sess ( ) , & mut db) ;
530+
531+ let sess = self . sess ( ) ;
532+ match diagnostic {
533+ BuiltinLintDiagnostics :: Normal => ( ) ,
534+ BuiltinLintDiagnostics :: BareTraitObject ( span, is_global) => {
535+ let ( sugg, app) = match sess. source_map ( ) . span_to_snippet ( span) {
536+ Ok ( s) if is_global => {
537+ ( format ! ( "dyn ({})" , s) , Applicability :: MachineApplicable )
538+ }
539+ Ok ( s) => ( format ! ( "dyn {}" , s) , Applicability :: MachineApplicable ) ,
540+ Err ( _) => ( "dyn <type>" . to_string ( ) , Applicability :: HasPlaceholders ) ,
541+ } ;
542+ db. span_suggestion ( span, "use `dyn`" , sugg, app) ;
543+ }
544+ BuiltinLintDiagnostics :: AbsPathWithModule ( span) => {
545+ let ( sugg, app) = match sess. source_map ( ) . span_to_snippet ( span) {
546+ Ok ( ref s) => {
547+ // FIXME(Manishearth) ideally the emitting code
548+ // can tell us whether or not this is global
549+ let opt_colon = if s. trim_start ( ) . starts_with ( "::" ) { "" } else { "::" } ;
550+
551+ ( format ! ( "crate{}{}" , opt_colon, s) , Applicability :: MachineApplicable )
552+ }
553+ Err ( _) => ( "crate::<path>" . to_string ( ) , Applicability :: HasPlaceholders ) ,
554+ } ;
555+ db. span_suggestion ( span, "use `crate`" , sugg, app) ;
556+ }
557+ BuiltinLintDiagnostics :: ProcMacroDeriveResolutionFallback ( span) => {
558+ db. span_label (
559+ span,
560+ "names from parent modules are not accessible without an explicit import" ,
561+ ) ;
562+ }
563+ BuiltinLintDiagnostics :: MacroExpandedMacroExportsAccessedByAbsolutePaths ( span_def) => {
564+ db. span_note ( span_def, "the macro is defined here" ) ;
565+ }
566+ BuiltinLintDiagnostics :: ElidedLifetimesInPaths (
567+ n,
568+ path_span,
569+ incl_angl_brckt,
570+ insertion_span,
571+ anon_lts,
572+ ) => {
573+ add_elided_lifetime_in_path_suggestion (
574+ sess,
575+ & mut db,
576+ n,
577+ path_span,
578+ incl_angl_brckt,
579+ insertion_span,
580+ anon_lts,
581+ ) ;
582+ }
583+ BuiltinLintDiagnostics :: UnknownCrateTypes ( span, note, sugg) => {
584+ db. span_suggestion ( span, & note, sugg, Applicability :: MaybeIncorrect ) ;
585+ }
586+ BuiltinLintDiagnostics :: UnusedImports ( message, replaces) => {
587+ if !replaces. is_empty ( ) {
588+ db. tool_only_multipart_suggestion (
589+ & message,
590+ replaces,
591+ Applicability :: MachineApplicable ,
592+ ) ;
593+ }
594+ }
595+ BuiltinLintDiagnostics :: RedundantImport ( spans, ident) => {
596+ for ( span, is_imported) in spans {
597+ let introduced = if is_imported { "imported" } else { "defined" } ;
598+ db. span_label (
599+ span,
600+ format ! ( "the item `{}` is already {} here" , ident, introduced) ,
601+ ) ;
602+ }
603+ }
604+ BuiltinLintDiagnostics :: DeprecatedMacro ( suggestion, span) => {
605+ stability:: deprecation_suggestion ( & mut db, suggestion, span)
606+ }
607+ }
608+
488609 db. emit ( ) ;
489610 }
490611
0 commit comments