@@ -40,8 +40,10 @@ use std::cmp;
40
40
use std:: default:: Default as StdDefault ;
41
41
use std:: mem;
42
42
use std:: fmt;
43
+ use std:: ops:: Deref ;
43
44
use syntax:: attr;
44
45
use syntax:: ast;
46
+ use syntax:: symbol:: Symbol ;
45
47
use syntax_pos:: { MultiSpan , Span } ;
46
48
use errors:: { self , Diagnostic , DiagnosticBuilder } ;
47
49
use hir;
@@ -299,8 +301,9 @@ impl LintStore {
299
301
check_lint_name_cmdline ( sess, self ,
300
302
& lint_name[ ..] , level) ;
301
303
304
+ let lint_flag_val = Symbol :: intern ( & lint_name) ;
302
305
match self . find_lint ( & lint_name[ ..] , sess, None ) {
303
- Ok ( lint_id) => self . set_level ( lint_id, ( level, CommandLine ) ) ,
306
+ Ok ( lint_id) => self . set_level ( lint_id, ( level, CommandLine ( lint_flag_val ) ) ) ,
304
307
Err ( FindLintError :: Removed ) => { }
305
308
Err ( _) => {
306
309
match self . lint_groups . iter ( ) . map ( |( & x, pair) | ( x, pair. 0 . clone ( ) ) )
@@ -310,7 +313,7 @@ impl LintStore {
310
313
Some ( v) => {
311
314
v. iter ( )
312
315
. map ( |lint_id : & LintId |
313
- self . set_level ( * lint_id, ( level, CommandLine ) ) )
316
+ self . set_level ( * lint_id, ( level, CommandLine ( lint_flag_val ) ) ) )
314
317
. collect :: < Vec < ( ) > > ( ) ;
315
318
}
316
319
None => {
@@ -446,42 +449,54 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
446
449
-> DiagnosticBuilder < ' a >
447
450
where S : Into < MultiSpan >
448
451
{
449
- let ( mut level, source) = lvlsrc;
452
+ let ( level, source) = lvlsrc;
450
453
if level == Allow {
451
454
return sess. diagnostic ( ) . struct_dummy ( ) ;
452
455
}
453
456
454
457
let name = lint. name_lower ( ) ;
455
458
let mut def = None ;
456
- let msg = match source {
457
- Default => {
458
- format ! ( "{}, #[{}({})] on by default" , msg,
459
- level. as_str( ) , name)
460
- } ,
461
- CommandLine => {
462
- format ! ( "{} [-{} {}]" , msg,
463
- match level {
464
- Warn => 'W' , Deny => 'D' , Forbid => 'F' ,
465
- Allow => bug!( )
466
- } , name. replace( "_" , "-" ) )
467
- } ,
468
- Node ( src) => {
469
- def = Some ( src) ;
470
- msg. to_string ( )
471
- }
472
- } ;
473
459
474
- // For purposes of printing, we can treat forbid as deny.
475
- if level == Forbid { level = Deny ; }
460
+ // Except for possible note details, forbid behaves like deny.
461
+ let effective_level = if level == Forbid { Deny } else { level } ;
476
462
477
- let mut err = match ( level , span) {
463
+ let mut err = match ( effective_level , span) {
478
464
( Warn , Some ( sp) ) => sess. struct_span_warn ( sp, & msg[ ..] ) ,
479
465
( Warn , None ) => sess. struct_warn ( & msg[ ..] ) ,
480
466
( Deny , Some ( sp) ) => sess. struct_span_err ( sp, & msg[ ..] ) ,
481
467
( Deny , None ) => sess. struct_err ( & msg[ ..] ) ,
482
468
_ => bug ! ( "impossible level in raw_emit_lint" ) ,
483
469
} ;
484
470
471
+ match source {
472
+ Default => {
473
+ err. note ( & format ! ( "#[{}({})] on by default" , level. as_str( ) , name) ) ;
474
+ } ,
475
+ CommandLine ( lint_flag_val) => {
476
+ let flag = match level {
477
+ Warn => "-W" , Deny => "-D" , Forbid => "-F" ,
478
+ Allow => bug ! ( "earlier conditional return should handle Allow case" )
479
+ } ;
480
+ let hyphen_case_lint_name = name. replace ( "_" , "-" ) ;
481
+ if lint_flag_val. as_str ( ) . deref ( ) == name {
482
+ err. note ( & format ! ( "requested on the command line with `{} {}`" ,
483
+ flag, hyphen_case_lint_name) ) ;
484
+ } else {
485
+ let hyphen_case_flag_val = lint_flag_val. as_str ( ) . replace ( "_" , "-" ) ;
486
+ err. note ( & format ! ( "`{} {}` implied by `{} {}`" ,
487
+ flag, hyphen_case_lint_name, flag, hyphen_case_flag_val) ) ;
488
+ }
489
+ } ,
490
+ Node ( lint_attr_name, src) => {
491
+ def = Some ( src) ;
492
+ if lint_attr_name. as_str ( ) . deref ( ) != name {
493
+ let level_str = level. as_str ( ) ;
494
+ err. note ( & format ! ( "#[{}({})] implied by #[{}({})]" ,
495
+ level_str, name, level_str, lint_attr_name) ) ;
496
+ }
497
+ }
498
+ }
499
+
485
500
// Check for future incompatibility lints and issue a stronger warning.
486
501
if let Some ( future_incompatible) = lints. future_incompatible ( LintId :: of ( lint) ) {
487
502
let explanation = format ! ( "this was previously accepted by the compiler \
@@ -649,6 +664,8 @@ pub trait LintContext<'tcx>: Sized {
649
664
}
650
665
} ;
651
666
667
+ let lint_attr_name = result. expect ( "lint attribute should be well-formed" ) . 0 ;
668
+
652
669
for ( lint_id, level, span) in v {
653
670
let ( now, now_source) = self . lints ( ) . get_level_source ( lint_id) ;
654
671
if now == Forbid && level != Forbid {
@@ -660,19 +677,19 @@ pub trait LintContext<'tcx>: Sized {
660
677
diag_builder. span_label ( span, & format ! ( "overruled by previous forbid" ) ) ;
661
678
match now_source {
662
679
LintSource :: Default => & mut diag_builder,
663
- LintSource :: Node ( forbid_source_span) => {
680
+ LintSource :: Node ( _ , forbid_source_span) => {
664
681
diag_builder. span_label ( forbid_source_span,
665
682
& format ! ( "`forbid` level set here" ) )
666
683
} ,
667
- LintSource :: CommandLine => {
684
+ LintSource :: CommandLine ( _ ) => {
668
685
diag_builder. note ( "`forbid` lint level was set on command line" )
669
686
}
670
687
} . emit ( )
671
688
} else if now != level {
672
689
let src = self . lints ( ) . get_level_source ( lint_id) . 1 ;
673
690
self . level_stack ( ) . push ( ( lint_id, ( now, src) ) ) ;
674
691
pushed += 1 ;
675
- self . mut_lints ( ) . set_level ( lint_id, ( level, Node ( span) ) ) ;
692
+ self . mut_lints ( ) . set_level ( lint_id, ( level, Node ( lint_attr_name , span) ) ) ;
676
693
}
677
694
}
678
695
}
0 commit comments