@@ -22,7 +22,7 @@ use rustc_session::lint::builtin::{
22
22
} ;
23
23
use rustc_session:: parse:: feature_err;
24
24
use rustc_span:: symbol:: { sym, Symbol } ;
25
- use rustc_span:: { Span , DUMMY_SP } ;
25
+ use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
26
26
27
27
pub ( crate ) fn target_from_impl_item < ' tcx > (
28
28
tcx : TyCtxt < ' tcx > ,
@@ -67,6 +67,7 @@ impl CheckAttrVisitor<'tcx> {
67
67
item : Option < ItemLike < ' _ > > ,
68
68
) {
69
69
let mut is_valid = true ;
70
+ let mut specified_inline = None ;
70
71
let attrs = self . tcx . hir ( ) . attrs ( hir_id) ;
71
72
for attr in attrs {
72
73
is_valid &= match attr. name_or_empty ( ) {
@@ -77,7 +78,7 @@ impl CheckAttrVisitor<'tcx> {
77
78
sym:: track_caller => {
78
79
self . check_track_caller ( hir_id, & attr. span , attrs, span, target)
79
80
}
80
- sym:: doc => self . check_doc_attrs ( attr, hir_id, target) ,
81
+ sym:: doc => self . check_doc_attrs ( attr, hir_id, target, & mut specified_inline ) ,
81
82
sym:: no_link => self . check_no_link ( hir_id, & attr, span, target) ,
82
83
sym:: export_name => self . check_export_name ( hir_id, & attr, span, target) ,
83
84
sym:: rustc_args_required_const => {
@@ -564,6 +565,60 @@ impl CheckAttrVisitor<'tcx> {
564
565
true
565
566
}
566
567
568
+ fn check_doc_inline (
569
+ & self ,
570
+ attr : & Attribute ,
571
+ meta : & NestedMetaItem ,
572
+ hir_id : HirId ,
573
+ target : Target ,
574
+ specified_inline : & mut Option < ( bool , Span ) > ,
575
+ ) -> bool {
576
+ if target == Target :: Use {
577
+ let do_inline = meta. name_or_empty ( ) == sym:: inline;
578
+ if let Some ( ( prev_inline, prev_span) ) = * specified_inline {
579
+ if do_inline != prev_inline {
580
+ let mut spans = MultiSpan :: from_spans ( vec ! [ prev_span, meta. span( ) ] ) ;
581
+ spans. push_span_label ( prev_span, String :: from ( "this attribute..." ) ) ;
582
+ spans. push_span_label (
583
+ meta. span ( ) ,
584
+ String :: from ( "...conflicts with this attribute" ) ,
585
+ ) ;
586
+ self . tcx
587
+ . sess
588
+ . struct_span_err ( spans, "conflicting doc inlining attributes" )
589
+ . help ( "remove one of the conflicting attributes" )
590
+ . emit ( ) ;
591
+ return false ;
592
+ }
593
+ true
594
+ } else {
595
+ * specified_inline = Some ( ( do_inline, meta. span ( ) ) ) ;
596
+ true
597
+ }
598
+ } else {
599
+ self . tcx . struct_span_lint_hir (
600
+ INVALID_DOC_ATTRIBUTES ,
601
+ hir_id,
602
+ meta. span ( ) ,
603
+ |lint| {
604
+ let mut err = lint. build (
605
+ "this attribute can only be applied to a `use` item" ,
606
+ ) ;
607
+ err. span_label ( meta. span ( ) , "only applicable on `use` items" ) ;
608
+ if attr. style == AttrStyle :: Outer {
609
+ err. span_label (
610
+ self . tcx . hir ( ) . span ( hir_id) ,
611
+ "not a `use` item" ,
612
+ ) ;
613
+ }
614
+ err. note ( "read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information" )
615
+ . emit ( ) ;
616
+ } ,
617
+ ) ;
618
+ false
619
+ }
620
+ }
621
+
567
622
fn check_attr_not_crate_level (
568
623
& self ,
569
624
meta : & NestedMetaItem ,
@@ -628,7 +683,13 @@ impl CheckAttrVisitor<'tcx> {
628
683
true
629
684
}
630
685
631
- fn check_doc_attrs ( & self , attr : & Attribute , hir_id : HirId , target : Target ) -> bool {
686
+ fn check_doc_attrs (
687
+ & self ,
688
+ attr : & Attribute ,
689
+ hir_id : HirId ,
690
+ target : Target ,
691
+ specified_inline : & mut Option < ( bool , Span ) > ,
692
+ ) -> bool {
632
693
let mut is_valid = true ;
633
694
634
695
if let Some ( list) = attr. meta ( ) . and_then ( |mi| mi. meta_item_list ( ) . map ( |l| l. to_vec ( ) ) ) {
@@ -661,33 +722,18 @@ impl CheckAttrVisitor<'tcx> {
661
722
is_valid = false ;
662
723
}
663
724
664
- sym:: inline | sym:: no_inline if target != Target :: Use => {
665
- self . tcx . struct_span_lint_hir (
666
- INVALID_DOC_ATTRIBUTES ,
725
+ sym:: inline | sym:: no_inline
726
+ if !self . check_doc_inline (
727
+ & attr,
728
+ & meta,
667
729
hir_id,
668
- meta. span ( ) ,
669
- |lint| {
670
- let mut err = lint. build (
671
- "this attribute can only be applied to a `use` item" ,
672
- ) ;
673
- err. span_label ( meta. span ( ) , "only applicable on `use` items" ) ;
674
- if attr. style == AttrStyle :: Outer {
675
- err. span_label (
676
- self . tcx . hir ( ) . span ( hir_id) ,
677
- "not a `use` item" ,
678
- ) ;
679
- }
680
- err. note ( "read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information" )
681
- . emit ( ) ;
682
- } ,
683
- ) ;
730
+ target,
731
+ specified_inline,
732
+ ) =>
733
+ {
684
734
is_valid = false ;
685
735
}
686
736
687
- sym:: inline | sym:: no_inline => {
688
- // FIXME(#80275): conflicting inline attributes
689
- }
690
-
691
737
// no_default_passes: deprecated
692
738
// passes: deprecated
693
739
// plugins: removed, but rustdoc warns about it itself
@@ -700,10 +746,12 @@ impl CheckAttrVisitor<'tcx> {
700
746
| sym:: html_playground_url
701
747
| sym:: html_root_url
702
748
| sym:: include
749
+ | sym:: inline
703
750
| sym:: issue_tracker_base_url
704
751
| sym:: keyword
705
752
| sym:: masked
706
753
| sym:: no_default_passes
754
+ | sym:: no_inline
707
755
| sym:: notable_trait
708
756
| sym:: passes
709
757
| sym:: plugins
0 commit comments