Skip to content

Commit 2c10688

Browse files
committed
Auto merge of rust-lang#85457 - jyn514:remove-doc-include, r=GuillaumeGomez
Remove `doc(include)` This nightly feature is redundant now that `extended_key_value_attributes` is stable (rust-lang#83366). `@rust-lang/rustdoc` not sure if you think this needs FCP; there was already an FCP in rust-lang#82539, but technically it was for deprecating, not removing the feature altogether. This should not be merged before rust-lang#83366. cc `@petrochenkov`
2 parents 9e6f0e8 + 15fec1f commit 2c10688

File tree

28 files changed

+79
-449
lines changed

28 files changed

+79
-449
lines changed

Diff for: compiler/rustc_ast_passes/src/feature_gate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
318318
}}
319319

320320
gate_doc!(
321-
include => external_doc
322321
cfg => doc_cfg
323322
masked => doc_masked
324323
notable_trait => doc_notable_trait

Diff for: compiler/rustc_expand/src/base.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1068,11 +1068,11 @@ impl<'a> ExtCtxt<'a> {
10681068
self.resolver.check_unused_macros();
10691069
}
10701070

1071-
/// Resolves a path mentioned inside Rust code.
1071+
/// Resolves a `path` mentioned inside Rust code, returning an absolute path.
10721072
///
1073-
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
1073+
/// This unifies the logic used for resolving `include_X!`.
10741074
///
1075-
/// Returns an absolute path to the file that `path` refers to.
1075+
/// FIXME: move this to `rustc_builtin_macros` and make it private.
10761076
pub fn resolve_path(
10771077
&self,
10781078
path: impl Into<PathBuf>,

Diff for: compiler/rustc_expand/src/expand.rs

+5-139
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ use rustc_ast::ptr::P;
1212
use rustc_ast::token;
1313
use rustc_ast::tokenstream::TokenStream;
1414
use rustc_ast::visit::{self, AssocCtxt, Visitor};
15-
use rustc_ast::{AstLike, AttrItem, Block, Inline, ItemKind, LitKind, MacArgs};
15+
use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs};
1616
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
1717
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
1818
use rustc_ast_pretty::pprust;
19-
use rustc_attr::{self as attr, is_builtin_attr};
19+
use rustc_attr::is_builtin_attr;
2020
use rustc_data_structures::map_in_place::MapInPlace;
2121
use rustc_data_structures::stack::ensure_sufficient_stack;
2222
use rustc_data_structures::sync::Lrc;
@@ -28,15 +28,14 @@ use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
2828
use rustc_session::lint::BuiltinLintDiagnostics;
2929
use rustc_session::parse::{feature_err, ParseSess};
3030
use rustc_session::Limit;
31-
use rustc_span::symbol::{sym, Ident, Symbol};
32-
use rustc_span::{ExpnId, FileName, Span, DUMMY_SP};
31+
use rustc_span::symbol::{sym, Ident};
32+
use rustc_span::{ExpnId, FileName, Span};
3333

3434
use smallvec::{smallvec, SmallVec};
35-
use std::io::ErrorKind;
3635
use std::ops::DerefMut;
3736
use std::path::PathBuf;
3837
use std::rc::Rc;
39-
use std::{iter, mem, slice};
38+
use std::{iter, mem};
4039

4140
macro_rules! ast_fragments {
4241
(
@@ -1524,139 +1523,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
15241523
noop_flat_map_generic_param(param, self)
15251524
}
15261525

1527-
fn visit_attribute(&mut self, at: &mut ast::Attribute) {
1528-
// turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
1529-
// contents="file contents")]` attributes
1530-
if !self.cx.sess.check_name(at, sym::doc) {
1531-
return noop_visit_attribute(at, self);
1532-
}
1533-
1534-
if let Some(list) = at.meta_item_list() {
1535-
if !list.iter().any(|it| it.has_name(sym::include)) {
1536-
return noop_visit_attribute(at, self);
1537-
}
1538-
1539-
let mut items = vec![];
1540-
1541-
for mut it in list {
1542-
if !it.has_name(sym::include) {
1543-
items.push({
1544-
noop_visit_meta_list_item(&mut it, self);
1545-
it
1546-
});
1547-
continue;
1548-
}
1549-
1550-
if let Some(file) = it.value_str() {
1551-
let err_count = self.cx.sess.parse_sess.span_diagnostic.err_count();
1552-
self.check_attributes(slice::from_ref(at));
1553-
if self.cx.sess.parse_sess.span_diagnostic.err_count() > err_count {
1554-
// avoid loading the file if they haven't enabled the feature
1555-
return noop_visit_attribute(at, self);
1556-
}
1557-
1558-
let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) {
1559-
Ok(filename) => filename,
1560-
Err(mut err) => {
1561-
err.emit();
1562-
continue;
1563-
}
1564-
};
1565-
1566-
match self.cx.source_map().load_file(&filename) {
1567-
Ok(source_file) => {
1568-
let src = source_file
1569-
.src
1570-
.as_ref()
1571-
.expect("freshly loaded file should have a source");
1572-
let src_interned = Symbol::intern(src.as_str());
1573-
1574-
let include_info = vec![
1575-
ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
1576-
Ident::with_dummy_span(sym::file),
1577-
file,
1578-
DUMMY_SP,
1579-
)),
1580-
ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
1581-
Ident::with_dummy_span(sym::contents),
1582-
src_interned,
1583-
DUMMY_SP,
1584-
)),
1585-
];
1586-
1587-
let include_ident = Ident::with_dummy_span(sym::include);
1588-
let item = attr::mk_list_item(include_ident, include_info);
1589-
items.push(ast::NestedMetaItem::MetaItem(item));
1590-
}
1591-
Err(e) => {
1592-
let lit_span = it.name_value_literal_span().unwrap();
1593-
1594-
if e.kind() == ErrorKind::InvalidData {
1595-
self.cx
1596-
.struct_span_err(
1597-
lit_span,
1598-
&format!("{} wasn't a utf-8 file", filename.display()),
1599-
)
1600-
.span_label(lit_span, "contains invalid utf-8")
1601-
.emit();
1602-
} else {
1603-
let mut err = self.cx.struct_span_err(
1604-
lit_span,
1605-
&format!("couldn't read {}: {}", filename.display(), e),
1606-
);
1607-
err.span_label(lit_span, "couldn't read file");
1608-
1609-
err.emit();
1610-
}
1611-
}
1612-
}
1613-
} else {
1614-
let mut err = self
1615-
.cx
1616-
.struct_span_err(it.span(), "expected path to external documentation");
1617-
1618-
// Check if the user erroneously used `doc(include(...))` syntax.
1619-
let literal = it.meta_item_list().and_then(|list| {
1620-
if list.len() == 1 {
1621-
list[0].literal().map(|literal| &literal.kind)
1622-
} else {
1623-
None
1624-
}
1625-
});
1626-
1627-
let (path, applicability) = match &literal {
1628-
Some(LitKind::Str(path, ..)) => {
1629-
(path.to_string(), Applicability::MachineApplicable)
1630-
}
1631-
_ => (String::from("<path>"), Applicability::HasPlaceholders),
1632-
};
1633-
1634-
err.span_suggestion(
1635-
it.span(),
1636-
"provide a file path with `=`",
1637-
format!("include = \"{}\"", path),
1638-
applicability,
1639-
);
1640-
1641-
err.emit();
1642-
}
1643-
}
1644-
1645-
let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
1646-
*at = ast::Attribute {
1647-
kind: ast::AttrKind::Normal(
1648-
AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span), tokens: None },
1649-
None,
1650-
),
1651-
span: at.span,
1652-
id: at.id,
1653-
style: at.style,
1654-
};
1655-
} else {
1656-
noop_visit_attribute(at, self)
1657-
}
1658-
}
1659-
16601526
fn visit_id(&mut self, id: &mut ast::NodeId) {
16611527
if self.monotonic {
16621528
debug_assert_eq!(*id, ast::DUMMY_NODE_ID);

Diff for: compiler/rustc_feature/src/active.rs

-3
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,6 @@ declare_features! (
370370
/// Allows `#[doc(masked)]`.
371371
(active, doc_masked, "1.21.0", Some(44027), None),
372372

373-
/// Allows `#[doc(include = "some-file")]`.
374-
(active, external_doc, "1.22.0", Some(44732), None),
375-
376373
/// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`.
377374
(active, crate_visibility_modifier, "1.23.0", Some(53120), None),
378375

Diff for: compiler/rustc_feature/src/removed.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ declare_features! (
140140
(removed, const_fn, "1.54.0", Some(57563), None,
141141
Some("split into finer-grained feature gates")),
142142

143+
/// Allows `#[doc(include = "some-file")]`.
144+
(removed, external_doc, "1.54.0", Some(44732), None,
145+
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
146+
143147
// -------------------------------------------------------------------------
144148
// feature-group-end: removed features
145149
// -------------------------------------------------------------------------

Diff for: compiler/rustc_lint/src/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool {
489489

490490
if let Some(list) = attr.meta_item_list() {
491491
for meta in list {
492-
if meta.has_name(sym::include) || meta.has_name(sym::hidden) {
492+
if meta.has_name(sym::hidden) {
493493
return true;
494494
}
495495
}

Diff for: compiler/rustc_passes/src/check_attr.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ impl CheckAttrVisitor<'tcx> {
705705
let mut is_valid = true;
706706

707707
if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) {
708-
for meta in list {
708+
for meta in &list {
709709
if let Some(i_meta) = meta.meta_item() {
710710
match i_meta.name_or_empty() {
711711
sym::alias
@@ -757,7 +757,6 @@ impl CheckAttrVisitor<'tcx> {
757757
| sym::html_no_source
758758
| sym::html_playground_url
759759
| sym::html_root_url
760-
| sym::include
761760
| sym::inline
762761
| sym::issue_tracker_base_url
763762
| sym::keyword
@@ -792,6 +791,30 @@ impl CheckAttrVisitor<'tcx> {
792791
);
793792
diag.note("`doc(spotlight)` is now a no-op");
794793
}
794+
if i_meta.has_name(sym::include) {
795+
if let Some(value) = i_meta.value_str() {
796+
// if there are multiple attributes, the suggestion would suggest deleting all of them, which is incorrect
797+
let applicability = if list.len() == 1 {
798+
Applicability::MachineApplicable
799+
} else {
800+
Applicability::MaybeIncorrect
801+
};
802+
let inner = if attr.style == AttrStyle::Inner {
803+
"!"
804+
} else {
805+
""
806+
};
807+
diag.span_suggestion(
808+
attr.meta().unwrap().span,
809+
"use `doc = include_str!` instead",
810+
format!(
811+
"#{}[doc = include_str!(\"{}\")]",
812+
inner, value
813+
),
814+
applicability,
815+
);
816+
}
817+
}
795818
diag.emit();
796819
},
797820
);

Diff for: compiler/rustc_save_analysis/src/lib.rs

-14
Original file line numberDiff line numberDiff line change
@@ -826,20 +826,6 @@ impl<'tcx> SaveContext<'tcx> {
826826
// FIXME: Should save-analysis beautify doc strings itself or leave it to users?
827827
result.push_str(&beautify_doc_string(val).as_str());
828828
result.push('\n');
829-
} else if self.tcx.sess.check_name(attr, sym::doc) {
830-
if let Some(meta_list) = attr.meta_item_list() {
831-
meta_list
832-
.into_iter()
833-
.filter(|it| it.has_name(sym::include))
834-
.filter_map(|it| it.meta_item_list().map(|l| l.to_owned()))
835-
.flat_map(|it| it)
836-
.filter(|meta| meta.has_name(sym::contents))
837-
.filter_map(|meta| meta.value_str())
838-
.for_each(|val| {
839-
result.push_str(&val.as_str());
840-
result.push('\n');
841-
});
842-
}
843829
}
844830
}
845831

Diff for: library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@
159159
#![feature(const_fn_transmute)]
160160
#![feature(abi_unadjusted)]
161161
#![feature(adx_target_feature)]
162-
#![feature(external_doc)]
163162
#![feature(associated_type_bounds)]
164163
#![feature(const_caller_location)]
165164
#![feature(slice_ptr_get)]

Diff for: src/doc/rustdoc/src/documentation-tests.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,7 @@ without including it in your main documentation. For example, you could write th
424424
`lib.rs` to test your README as part of your doctests:
425425

426426
```rust,no_run
427-
#![feature(external_doc)]
428-
429-
#[doc(include = "../README.md")]
427+
#[doc = include_str!("../README.md")]
430428
#[cfg(doctest)]
431429
pub struct ReadmeDoctests;
432430
```

Diff for: src/doc/rustdoc/src/unstable-features.md

-16
Original file line numberDiff line numberDiff line change
@@ -131,22 +131,6 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
131131
[unstable-masked]: ../unstable-book/language-features/doc-masked.html
132132
[issue-masked]: https://github.com/rust-lang/rust/issues/44027
133133

134-
### Include external files as API documentation
135-
136-
As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This
137-
is useful if certain documentation is so long that it would break the flow of reading the source.
138-
Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` will ask Rustdoc to
139-
instead read that file and use it as if it were written inline.
140-
141-
[RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990
142-
143-
`#[doc(include = "...")]` currently requires the `#![feature(external_doc)]` feature gate. For more
144-
information, see [its chapter in the Unstable Book][unstable-include] and [its tracking
145-
issue][issue-include].
146-
147-
[unstable-include]: ../unstable-book/language-features/external-doc.html
148-
[issue-include]: https://github.com/rust-lang/rust/issues/44732
149-
150134
## Unstable command-line arguments
151135

152136
These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are

Diff for: src/doc/unstable-book/src/language-features/external-doc.md

-40
This file was deleted.

0 commit comments

Comments
 (0)