Skip to content

Commit 460d4ac

Browse files
committed
Deprecate doc(include)
## Why deprecate doc(include)? This nightly feature is a strictly less general version of `extended_key_value_attributes`, which looks like this: ``` #[doc = include_str!("docs.md")] ``` In particular, that feature allows manipulating the filename and included docs in a way that `doc(include)` cannot, due to eager evaluation: ``` #[doc = concat!( "These are my docs: ", include_str!(concat!(env!("OUT_DIR"), "generated_docs.md")) )] ``` For more about eager evaluation and how it impacts macro parsing, see petrochenkov's excellent writeup: https://internals.rust-lang.org/t/macro-expansion-points-in-attributes/11455 Given that `#[doc(include)]` offers no features that `extended_key_value_attributes` cannot, it makes no sense for the language and rustdoc to maintain it indefinitely. This deprecates `doc(include)` and adds a structured suggestion to switch to switch to `doc = include_str!` instead. ## Implementation Notably, this changes attribute cleaning to pass in whether an item is local or not. This is necessary to avoid warning about `doc(include)` in dependencies (see rust-lang#82284 for the sort of trouble that can cause).
1 parent 69e1d22 commit 460d4ac

File tree

8 files changed

+96
-20
lines changed

8 files changed

+96
-20
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::clean::{self, Attributes, GetDefId, ToSource, TypeKind};
1919
use crate::core::DocContext;
2020
use crate::formats::item_type::ItemType;
2121

22+
use super::clean_attrs;
2223
use super::Clean;
2324

2425
type Attrs<'hir> = rustc_middle::ty::Attributes<'hir>;
@@ -121,7 +122,7 @@ crate fn try_inline(
121122
};
122123

123124
let target_attrs = load_attrs(cx, did);
124-
let attrs = box merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone);
125+
let attrs = box merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone, did.is_local());
125126

126127
cx.inlined.insert(did);
127128
let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name), kind, cx);
@@ -289,6 +290,7 @@ fn merge_attrs(
289290
parent_module: Option<DefId>,
290291
old_attrs: Attrs<'_>,
291292
new_attrs: Option<Attrs<'_>>,
293+
local: bool,
292294
) -> clean::Attributes {
293295
// NOTE: If we have additional attributes (from a re-export),
294296
// always insert them first. This ensure that re-export
@@ -297,14 +299,14 @@ fn merge_attrs(
297299
if let Some(inner) = new_attrs {
298300
if let Some(new_id) = parent_module {
299301
let diag = cx.sess().diagnostic();
300-
Attributes::from_ast(diag, old_attrs, Some((inner, new_id)))
302+
Attributes::from_ast(diag, old_attrs, Some((inner, new_id)), local)
301303
} else {
302304
let mut both = inner.to_vec();
303305
both.extend_from_slice(old_attrs);
304-
both.clean(cx)
306+
clean_attrs(&both, local, cx)
305307
}
306308
} else {
307-
old_attrs.clean(cx)
309+
clean_attrs(old_attrs, local, cx)
308310
}
309311
}
310312

@@ -415,7 +417,8 @@ crate fn build_impl(
415417

416418
debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
417419

418-
let attrs = box merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
420+
let attrs =
421+
box merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs, did.is_local());
419422
debug!("merged_attrs={:?}", attrs);
420423

421424
ret.push(clean::Item::from_def_id_and_attrs_and_parts(

src/librustdoc/clean/mod.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ impl Clean<ExternalCrate> for CrateNum {
108108
// rendering by delegating everything to a hash map.
109109
let mut as_primitive = |res: Res| {
110110
if let Res::Def(DefKind::Mod, def_id) = res {
111-
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
111+
// We already warned about any attributes on the module when cleaning it.
112+
// Don't warn a second time.
113+
let attrs = clean_attrs(cx.tcx.get_attrs(def_id), false, cx);
112114
let mut prim = None;
113115
for attr in attrs.lists(sym::doc) {
114116
if let Some(v) = attr.value_str() {
@@ -155,7 +157,7 @@ impl Clean<ExternalCrate> for CrateNum {
155157

156158
let mut as_keyword = |res: Res| {
157159
if let Res::Def(DefKind::Mod, def_id) = res {
158-
let attrs = tcx.get_attrs(def_id).clean(cx);
160+
let attrs = clean_attrs(tcx.get_attrs(def_id), false, cx);
159161
let mut keyword = None;
160162
for attr in attrs.lists(sym::doc) {
161163
if attr.has_name(sym::keyword) {
@@ -197,7 +199,8 @@ impl Clean<ExternalCrate> for CrateNum {
197199
ExternalCrate {
198200
name: tcx.crate_name(*self),
199201
src: krate_src,
200-
attrs: tcx.get_attrs(root).clean(cx),
202+
// The local crate was already cleaned, and all other crates are non-local.
203+
attrs: clean_attrs(tcx.get_attrs(root), false, cx),
201204
primitives,
202205
keywords,
203206
}
@@ -237,10 +240,8 @@ impl Clean<Item> for doctree::Module<'_> {
237240
}
238241
}
239242

240-
impl Clean<Attributes> for [ast::Attribute] {
241-
fn clean(&self, cx: &mut DocContext<'_>) -> Attributes {
242-
Attributes::from_ast(cx.sess().diagnostic(), self, None)
243-
}
243+
fn clean_attrs(attrs: &[ast::Attribute], local: bool, cx: &mut DocContext<'_>) -> Attributes {
244+
Attributes::from_ast(cx.sess().diagnostic(), attrs, None, local)
244245
}
245246

246247
impl Clean<GenericBound> for hir::GenericBound<'_> {
@@ -2124,7 +2125,7 @@ fn clean_extern_crate(
21242125
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
21252126
vec![Item {
21262127
name: Some(name),
2127-
attrs: box attrs.clean(cx),
2128+
attrs: box clean_attrs(attrs, true, cx),
21282129
span: krate.span.clean(cx),
21292130
def_id: crate_def_id,
21302131
visibility: krate.vis.clean(cx),

src/librustdoc/clean/types.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_ast::{self as ast, AttrStyle};
1616
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
1717
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1818
use rustc_data_structures::thin_vec::ThinVec;
19+
use rustc_errors::Applicability;
1920
use rustc_hir as hir;
2021
use rustc_hir::def::{CtorKind, Res};
2122
use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
@@ -32,11 +33,10 @@ use rustc_target::abi::VariantIdx;
3233
use rustc_target::spec::abi::Abi;
3334

3435
use crate::clean::cfg::Cfg;
35-
use crate::clean::external_path;
36-
use crate::clean::inline::{self, print_inlined_const};
3736
use crate::clean::types::Type::{QPath, ResolvedPath};
3837
use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
3938
use crate::clean::Clean;
39+
use crate::clean::{clean_attrs, external_path, inline};
4040
use crate::core::DocContext;
4141
use crate::formats::cache::Cache;
4242
use crate::formats::item_type::ItemType;
@@ -154,7 +154,7 @@ impl Item {
154154
def_id,
155155
name,
156156
kind,
157-
box cx.tcx.get_attrs(def_id).clean(cx),
157+
box clean_attrs(cx.tcx.get_attrs(def_id), def_id.is_local(), cx),
158158
cx,
159159
)
160160
}
@@ -739,9 +739,10 @@ impl Attributes {
739739
}
740740

741741
crate fn from_ast(
742-
diagnostic: &::rustc_errors::Handler,
742+
handler: &::rustc_errors::Handler,
743743
attrs: &[ast::Attribute],
744744
additional_attrs: Option<(&[ast::Attribute], DefId)>,
745+
local: bool,
745746
) -> Attributes {
746747
let mut doc_strings: Vec<DocFragment> = vec![];
747748
let mut sp = None;
@@ -800,10 +801,26 @@ impl Attributes {
800801
// Extracted #[doc(cfg(...))]
801802
match Cfg::parse(cfg_mi) {
802803
Ok(new_cfg) => cfg &= new_cfg,
803-
Err(e) => diagnostic.span_err(e.span, e.msg),
804+
Err(e) => handler.span_err(e.span, e.msg),
804805
}
805806
} else if let Some((filename, contents)) = Attributes::extract_include(&mi)
806807
{
808+
if local {
809+
let mut diag = handler
810+
.struct_span_warn(attr.span, "`doc(include)` is deprecated");
811+
diag.span_suggestion_verbose(
812+
attr.span,
813+
"use `#![feature(extended_key_value_attributes)]` instead",
814+
format!(
815+
"#{}[doc = include_str!(\"{}\")]",
816+
if attr.style == AttrStyle::Inner { "!" } else { "" },
817+
filename,
818+
),
819+
Applicability::MaybeIncorrect,
820+
);
821+
diag.emit();
822+
}
823+
807824
let line = doc_line;
808825
doc_line += contents.as_str().lines().count();
809826
let frag = DocFragment {
@@ -2001,7 +2018,7 @@ impl Constant {
20012018
crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
20022019
match self.kind {
20032020
ConstantKind::TyConst { ref expr } => expr.clone(),
2004-
ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2021+
ConstantKind::Extern { def_id } => inline::print_inlined_const(tcx, def_id),
20052022
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
20062023
print_const_expr(tcx, body)
20072024
}

src/librustdoc/doctest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
10931093
nested: F,
10941094
) {
10951095
let attrs = self.tcx.hir().attrs(hir_id);
1096-
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None);
1096+
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None, true);
10971097
if let Some(ref cfg) = attrs.cfg {
10981098
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
10991099
return;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![crate_name = "inner"]
2+
#![feature(external_doc)]
3+
#[doc(include = "docs.md")]
4+
pub struct HasDocInclude {}
5+
pub struct NoDocs {}

src/test/rustdoc-ui/auxiliary/docs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Here have some docs
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// aux-build:doc-include-deprecated.rs
2+
// check-pass
3+
#![feature(external_doc)]
4+
#![doc(include = "auxiliary/docs.md")] //~ WARNING deprecated
5+
6+
extern crate inner;
7+
8+
pub use inner::HasDocInclude;
9+
10+
#[doc(include = "auxiliary/docs.md")] //~ WARNING deprecated
11+
pub use inner::HasDocInclude as _;
12+
13+
#[doc(include = "auxiliary/docs.md")] //~ WARNING deprecated
14+
pub use inner::NoDocs;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
warning: `doc(include)` is deprecated
2+
--> $DIR/doc-include-deprecated.rs:10:1
3+
|
4+
LL | #[doc(include = "auxiliary/docs.md")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
help: use `#![feature(extended_key_value_attributes)]` instead
8+
|
9+
LL | #[doc = include_str!("auxiliary/docs.md")]
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
12+
warning: `doc(include)` is deprecated
13+
--> $DIR/doc-include-deprecated.rs:13:1
14+
|
15+
LL | #[doc(include = "auxiliary/docs.md")]
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
|
18+
help: use `#![feature(extended_key_value_attributes)]` instead
19+
|
20+
LL | #[doc = include_str!("auxiliary/docs.md")]
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22+
23+
warning: `doc(include)` is deprecated
24+
--> $DIR/doc-include-deprecated.rs:4:1
25+
|
26+
LL | #![doc(include = "auxiliary/docs.md")]
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
|
29+
help: use `#![feature(extended_key_value_attributes)]` instead
30+
|
31+
LL | #![doc = include_str!("auxiliary/docs.md")]
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33+
34+
warning: 3 warnings emitted
35+

0 commit comments

Comments
 (0)