17
17
use self :: TargetLint :: * ;
18
18
19
19
use crate :: hir:: map:: { definitions:: DisambiguatedDefPathData , DefPathData } ;
20
- use crate :: lint:: builtin:: BuiltinLintDiagnostics ;
21
20
use crate :: lint:: levels:: { LintLevelSets , LintLevelsBuilder } ;
22
21
use crate :: lint:: { EarlyLintPassObject , LateLintPassObject } ;
23
- use crate :: lint:: { FutureIncompatibleInfo , Level , Lint , LintBuffer , LintId } ;
24
22
use crate :: middle:: privacy:: AccessLevels ;
23
+ use crate :: middle:: stability;
25
24
use crate :: session:: Session ;
26
25
use crate :: ty:: layout:: { LayoutError , LayoutOf , TyLayout } ;
27
26
use crate :: ty:: { self , print:: Printer , subst:: GenericArg , Ty , TyCtxt } ;
28
27
use rustc_data_structures:: fx:: FxHashMap ;
29
28
use rustc_data_structures:: sync;
30
29
use rustc_error_codes:: * ;
31
- use rustc_errors:: { struct_span_err, DiagnosticBuilder } ;
30
+ use rustc_errors:: { pluralize , struct_span_err, Applicability , DiagnosticBuilder } ;
32
31
use rustc_hir as hir;
33
32
use rustc_hir:: def_id:: { CrateNum , DefId } ;
33
+ use rustc_session:: lint:: BuiltinLintDiagnostics ;
34
+ use rustc_session:: lint:: { FutureIncompatibleInfo , Level , Lint , LintBuffer , LintId } ;
34
35
use rustc_span:: { symbol:: Symbol , MultiSpan , Span , DUMMY_SP } ;
35
36
use syntax:: ast;
36
37
use syntax:: util:: lev_distance:: find_best_match_for_name;
@@ -64,17 +65,6 @@ pub struct LintStore {
64
65
lint_groups : FxHashMap < & ' static str , LintGroup > ,
65
66
}
66
67
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
-
78
68
/// The target of the `by_name` map, which accounts for renaming/deprecation.
79
69
enum TargetLint {
80
70
/// A direct lint target
@@ -477,6 +467,48 @@ impl LintPassObject for EarlyLintPassObject {}
477
467
478
468
impl LintPassObject for LateLintPassObject { }
479
469
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
+
480
512
pub trait LintContext : Sized {
481
513
type PassObject : LintPassObject ;
482
514
@@ -495,7 +527,85 @@ pub trait LintContext: Sized {
495
527
diagnostic : BuiltinLintDiagnostics ,
496
528
) {
497
529
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
+
499
609
db. emit ( ) ;
500
610
}
501
611
0 commit comments