1717use self :: TargetLint :: * ;
1818
1919use crate :: hir:: map:: { definitions:: DisambiguatedDefPathData , DefPathData } ;
20- use crate :: lint:: builtin:: BuiltinLintDiagnostics ;
2120use crate :: lint:: levels:: { LintLevelSets , LintLevelsBuilder } ;
2221use crate :: lint:: { EarlyLintPassObject , LateLintPassObject } ;
23- use crate :: lint:: { FutureIncompatibleInfo , Level , Lint , LintBuffer , LintId } ;
2422use crate :: middle:: privacy:: AccessLevels ;
23+ use crate :: middle:: stability;
2524use crate :: session:: Session ;
2625use crate :: ty:: layout:: { LayoutError , LayoutOf , TyLayout } ;
2726use crate :: ty:: { self , print:: Printer , subst:: GenericArg , Ty , TyCtxt } ;
2827use rustc_data_structures:: fx:: FxHashMap ;
2928use rustc_data_structures:: sync;
3029use rustc_error_codes:: * ;
31- use rustc_errors:: { struct_span_err, DiagnosticBuilder } ;
30+ use rustc_errors:: { pluralize , struct_span_err, Applicability , DiagnosticBuilder } ;
3231use rustc_hir as hir;
3332use rustc_hir:: def_id:: { CrateNum , DefId } ;
33+ use rustc_session:: lint:: BuiltinLintDiagnostics ;
34+ use rustc_session:: lint:: { FutureIncompatibleInfo , Level , Lint , LintBuffer , LintId } ;
3435use rustc_span:: { symbol:: Symbol , MultiSpan , Span , DUMMY_SP } ;
3536use syntax:: ast;
3637use syntax:: util:: lev_distance:: find_best_match_for_name;
@@ -64,17 +65,6 @@ pub struct LintStore {
6465 lint_groups : FxHashMap < & ' static str , LintGroup > ,
6566}
6667
67- /// Lints that are buffered up early on in the `Session` before the
68- /// `LintLevels` is calculated
69- #[ derive( PartialEq , Debug ) ]
70- pub struct BufferedEarlyLint {
71- pub lint_id : LintId ,
72- pub ast_id : ast:: NodeId ,
73- pub span : MultiSpan ,
74- pub msg : String ,
75- pub diagnostic : BuiltinLintDiagnostics ,
76- }
77-
7868/// The target of the `by_name` map, which accounts for renaming/deprecation.
7969enum TargetLint {
8070 /// A direct lint target
@@ -477,6 +467,48 @@ impl LintPassObject for EarlyLintPassObject {}
477467
478468impl LintPassObject for LateLintPassObject { }
479469
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+
480512pub trait LintContext : Sized {
481513 type PassObject : LintPassObject ;
482514
@@ -495,7 +527,85 @@ pub trait LintContext: Sized {
495527 diagnostic : BuiltinLintDiagnostics ,
496528 ) {
497529 let mut db = self . lookup ( lint, span, msg) ;
498- diagnostic. run ( 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+
499609 db. emit ( ) ;
500610 }
501611
0 commit comments