From 15fec1fb80b5264d7e2d3382478424abb9afb3d1 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 18 May 2021 21:46:41 -0400 Subject: [PATCH] Remove `doc(include)` --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 - compiler/rustc_expand/src/base.rs | 6 +- compiler/rustc_expand/src/expand.rs | 144 +----------------- compiler/rustc_feature/src/active.rs | 3 - compiler/rustc_feature/src/removed.rs | 4 + compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 27 +++- compiler/rustc_save_analysis/src/lib.rs | 14 -- library/core/src/lib.rs | 1 - src/doc/rustdoc/src/documentation-tests.md | 4 +- src/doc/rustdoc/src/unstable-features.md | 16 -- .../src/language-features/external-doc.md | 40 ----- src/librustdoc/clean/types.rs | 93 +---------- .../include_bytes_deps/main.rs | 4 +- .../run-make-fulldeps/save-analysis/foo.rs | 7 +- src/test/rustdoc-ui/doc-include-suggestion.rs | 10 ++ .../rustdoc-ui/doc-include-suggestion.stderr | 12 ++ .../rustdoc/auxiliary/external-cross-doc.md | 2 +- src/test/rustdoc/auxiliary/external-cross.rs | 6 +- src/test/rustdoc/auxiliary/external-doc.md | 2 +- src/test/rustdoc/external-doc.rs | 9 -- src/test/rustdoc/unindent.rs | 6 +- src/test/ui/extern/external-doc-error.rs | 31 ---- src/test/ui/extern/external-doc-error.stderr | 38 ----- .../feature-gate-external_doc.rs | 3 - .../feature-gate-external_doc.stderr | 21 --- .../clippy/clippy_lints/src/missing_doc.rs | 19 +-- .../clippy/tests/ui/missing-doc-crate.rs | 3 +- 28 files changed, 79 insertions(+), 449 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/external-doc.md create mode 100644 src/test/rustdoc-ui/doc-include-suggestion.rs create mode 100644 src/test/rustdoc-ui/doc-include-suggestion.stderr delete mode 100644 src/test/ui/extern/external-doc-error.rs delete mode 100644 src/test/ui/extern/external-doc-error.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-external_doc.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-external_doc.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 4996c2195efdf..664e138b39dc8 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -318,7 +318,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }} gate_doc!( - include => external_doc cfg => doc_cfg masked => doc_masked notable_trait => doc_notable_trait diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e1c218c640851..aab2741c85240 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1068,11 +1068,11 @@ impl<'a> ExtCtxt<'a> { self.resolver.check_unused_macros(); } - /// Resolves a path mentioned inside Rust code. + /// Resolves a `path` mentioned inside Rust code, returning an absolute path. /// - /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths. + /// This unifies the logic used for resolving `include_X!`. /// - /// Returns an absolute path to the file that `path` refers to. + /// FIXME: move this to `rustc_builtin_macros` and make it private. pub fn resolve_path( &self, path: impl Into, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f5c6bb3db6542..39c0447bd099e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -12,11 +12,11 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AstLike, AttrItem, Block, Inline, ItemKind, LitKind, MacArgs}; +use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; -use rustc_attr::{self as attr, is_builtin_attr}; +use rustc_attr::is_builtin_attr; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; @@ -28,15 +28,14 @@ use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; use rustc_session::Limit; -use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{ExpnId, FileName, Span, DUMMY_SP}; +use rustc_span::symbol::{sym, Ident}; +use rustc_span::{ExpnId, FileName, Span}; use smallvec::{smallvec, SmallVec}; -use std::io::ErrorKind; use std::ops::DerefMut; use std::path::PathBuf; use std::rc::Rc; -use std::{iter, mem, slice}; +use std::{iter, mem}; macro_rules! ast_fragments { ( @@ -1524,139 +1523,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { noop_flat_map_generic_param(param, self) } - fn visit_attribute(&mut self, at: &mut ast::Attribute) { - // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename", - // contents="file contents")]` attributes - if !self.cx.sess.check_name(at, sym::doc) { - return noop_visit_attribute(at, self); - } - - if let Some(list) = at.meta_item_list() { - if !list.iter().any(|it| it.has_name(sym::include)) { - return noop_visit_attribute(at, self); - } - - let mut items = vec![]; - - for mut it in list { - if !it.has_name(sym::include) { - items.push({ - noop_visit_meta_list_item(&mut it, self); - it - }); - continue; - } - - if let Some(file) = it.value_str() { - let err_count = self.cx.sess.parse_sess.span_diagnostic.err_count(); - self.check_attributes(slice::from_ref(at)); - if self.cx.sess.parse_sess.span_diagnostic.err_count() > err_count { - // avoid loading the file if they haven't enabled the feature - return noop_visit_attribute(at, self); - } - - let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) { - Ok(filename) => filename, - Err(mut err) => { - err.emit(); - continue; - } - }; - - match self.cx.source_map().load_file(&filename) { - Ok(source_file) => { - let src = source_file - .src - .as_ref() - .expect("freshly loaded file should have a source"); - let src_interned = Symbol::intern(src.as_str()); - - let include_info = vec![ - ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str( - Ident::with_dummy_span(sym::file), - file, - DUMMY_SP, - )), - ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str( - Ident::with_dummy_span(sym::contents), - src_interned, - DUMMY_SP, - )), - ]; - - let include_ident = Ident::with_dummy_span(sym::include); - let item = attr::mk_list_item(include_ident, include_info); - items.push(ast::NestedMetaItem::MetaItem(item)); - } - Err(e) => { - let lit_span = it.name_value_literal_span().unwrap(); - - if e.kind() == ErrorKind::InvalidData { - self.cx - .struct_span_err( - lit_span, - &format!("{} wasn't a utf-8 file", filename.display()), - ) - .span_label(lit_span, "contains invalid utf-8") - .emit(); - } else { - let mut err = self.cx.struct_span_err( - lit_span, - &format!("couldn't read {}: {}", filename.display(), e), - ); - err.span_label(lit_span, "couldn't read file"); - - err.emit(); - } - } - } - } else { - let mut err = self - .cx - .struct_span_err(it.span(), "expected path to external documentation"); - - // Check if the user erroneously used `doc(include(...))` syntax. - let literal = it.meta_item_list().and_then(|list| { - if list.len() == 1 { - list[0].literal().map(|literal| &literal.kind) - } else { - None - } - }); - - let (path, applicability) = match &literal { - Some(LitKind::Str(path, ..)) => { - (path.to_string(), Applicability::MachineApplicable) - } - _ => (String::from(""), Applicability::HasPlaceholders), - }; - - err.span_suggestion( - it.span(), - "provide a file path with `=`", - format!("include = \"{}\"", path), - applicability, - ); - - err.emit(); - } - } - - let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items); - *at = ast::Attribute { - kind: ast::AttrKind::Normal( - AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span), tokens: None }, - None, - ), - span: at.span, - id: at.id, - style: at.style, - }; - } else { - noop_visit_attribute(at, self) - } - } - fn visit_id(&mut self, id: &mut ast::NodeId) { if self.monotonic { debug_assert_eq!(*id, ast::DUMMY_NODE_ID); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a84737e80a09f..2054cd3e4c292 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -370,9 +370,6 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), - /// Allows `#[doc(include = "some-file")]`. - (active, external_doc, "1.22.0", Some(44732), None), - /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. (active, crate_visibility_modifier, "1.23.0", Some(53120), None), diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 138398825af58..71c10eb650754 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -140,6 +140,10 @@ declare_features! ( (removed, const_fn, "1.54.0", Some(57563), None, Some("split into finer-grained feature gates")), + /// Allows `#[doc(include = "some-file")]`. + (removed, external_doc, "1.54.0", Some(44732), None, + Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + // ------------------------------------------------------------------------- // feature-group-end: removed features // ------------------------------------------------------------------------- diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e7275374b8915..f6a84966f7a91 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -489,7 +489,7 @@ fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool { if let Some(list) = attr.meta_item_list() { for meta in list { - if meta.has_name(sym::include) || meta.has_name(sym::hidden) { + if meta.has_name(sym::hidden) { return true; } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bf574bbfbb5ae..91b6461151145 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -705,7 +705,7 @@ impl CheckAttrVisitor<'tcx> { let mut is_valid = true; if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) { - for meta in list { + for meta in &list { if let Some(i_meta) = meta.meta_item() { match i_meta.name_or_empty() { sym::alias @@ -757,7 +757,6 @@ impl CheckAttrVisitor<'tcx> { | sym::html_no_source | sym::html_playground_url | sym::html_root_url - | sym::include | sym::inline | sym::issue_tracker_base_url | sym::keyword @@ -792,6 +791,30 @@ impl CheckAttrVisitor<'tcx> { ); diag.note("`doc(spotlight)` is now a no-op"); } + if i_meta.has_name(sym::include) { + if let Some(value) = i_meta.value_str() { + // if there are multiple attributes, the suggestion would suggest deleting all of them, which is incorrect + let applicability = if list.len() == 1 { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + let inner = if attr.style == AttrStyle::Inner { + "!" + } else { + "" + }; + diag.span_suggestion( + attr.meta().unwrap().span, + "use `doc = include_str!` instead", + format!( + "#{}[doc = include_str!(\"{}\")]", + inner, value + ), + applicability, + ); + } + } diag.emit(); }, ); diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index bdffdd5311e3c..524c352fef515 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -826,20 +826,6 @@ impl<'tcx> SaveContext<'tcx> { // FIXME: Should save-analysis beautify doc strings itself or leave it to users? result.push_str(&beautify_doc_string(val).as_str()); result.push('\n'); - } else if self.tcx.sess.check_name(attr, sym::doc) { - if let Some(meta_list) = attr.meta_item_list() { - meta_list - .into_iter() - .filter(|it| it.has_name(sym::include)) - .filter_map(|it| it.meta_item_list().map(|l| l.to_owned())) - .flat_map(|it| it) - .filter(|meta| meta.has_name(sym::contents)) - .filter_map(|meta| meta.value_str()) - .for_each(|val| { - result.push_str(&val.as_str()); - result.push('\n'); - }); - } } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a023edaca9e94..a76d2d0a67852 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -160,7 +160,6 @@ #![feature(const_fn_transmute)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(external_doc)] #![feature(associated_type_bounds)] #![feature(const_caller_location)] #![feature(slice_ptr_get)] diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 8e3c622818954..cb7b85655b5a8 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -424,9 +424,7 @@ without including it in your main documentation. For example, you could write th `lib.rs` to test your README as part of your doctests: ```rust,no_run -#![feature(external_doc)] - -#[doc(include = "../README.md")] +#[doc = include_str!("../README.md")] #[cfg(doctest)] pub struct ReadmeDoctests; ``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 28b81a40265d3..e9b15666bb316 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -131,22 +131,6 @@ Book][unstable-masked] and [its tracking issue][issue-masked]. [unstable-masked]: ../unstable-book/language-features/doc-masked.html [issue-masked]: https://github.com/rust-lang/rust/issues/44027 -### Include external files as API documentation - -As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This -is useful if certain documentation is so long that it would break the flow of reading the source. -Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` will ask Rustdoc to -instead read that file and use it as if it were written inline. - -[RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990 - -`#[doc(include = "...")]` currently requires the `#![feature(external_doc)]` feature gate. For more -information, see [its chapter in the Unstable Book][unstable-include] and [its tracking -issue][issue-include]. - -[unstable-include]: ../unstable-book/language-features/external-doc.html -[issue-include]: https://github.com/rust-lang/rust/issues/44732 - ## Unstable command-line arguments These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are diff --git a/src/doc/unstable-book/src/language-features/external-doc.md b/src/doc/unstable-book/src/language-features/external-doc.md deleted file mode 100644 index effae5d299949..0000000000000 --- a/src/doc/unstable-book/src/language-features/external-doc.md +++ /dev/null @@ -1,40 +0,0 @@ -# `external_doc` - -The tracking issue for this feature is: [#44732] - -The `external_doc` feature allows the use of the `include` parameter to the `#[doc]` attribute, to -include external files in documentation. Use the attribute in place of, or in addition to, regular -doc comments and `#[doc]` attributes, and `rustdoc` will load the given file when it renders -documentation for your crate. - -With the following files in the same directory: - -`external-doc.md`: - -```markdown -# My Awesome Type - -This is the documentation for this spectacular type. -``` - -`lib.rs`: - -```no_run (needs-external-files) -#![feature(external_doc)] - -#[doc(include = "external-doc.md")] -pub struct MyAwesomeType; -``` - -`rustdoc` will load the file `external-doc.md` and use it as the documentation for the `MyAwesomeType` -struct. - -When locating files, `rustdoc` will base paths in the `src/` directory, as if they were alongside the -`lib.rs` for your crate. So if you want a `docs/` folder to live alongside the `src/` directory, -start your paths with `../docs/` for `rustdoc` to properly find the file. - -This feature was proposed in [RFC #1990] and initially implemented in PR [#44781]. - -[#44732]: https://github.com/rust-lang/rust/issues/44732 -[RFC #1990]: https://github.com/rust-lang/rfcs/pull/1990 -[#44781]: https://github.com/rust-lang/rust/pull/44781 diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3ae516bd6df7c..67397036cd332 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -809,7 +809,7 @@ impl AttributesExt for [ast::Attribute] { // #[doc(...)] if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) { for item in list { - // #[doc(include)] + // #[doc(hidden)] if !item.has_name(sym::cfg) { continue; } @@ -894,9 +894,6 @@ crate enum DocFragmentKind { SugaredDoc, /// A doc fragment created from a "raw" `#[doc=""]` attribute. RawDoc, - /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the - /// given filename and the file contents. - Include { filename: Symbol }, } // The goal of this function is to apply the `DocFragment` transformations that are required when @@ -930,18 +927,8 @@ impl<'a> FromIterator<&'a DocFragment> for String { where T: IntoIterator, { - let mut prev_kind: Option = None; iter.into_iter().fold(String::new(), |mut acc, frag| { - if !acc.is_empty() - && prev_kind - .take() - .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind) - .unwrap_or(false) - { - acc.push('\n'); - } add_doc_fragment(&mut acc, &frag); - prev_kind = Some(frag.kind); acc }) } @@ -988,45 +975,6 @@ impl Attributes { self.other_attrs.lists(name) } - /// Reads a `MetaItem` from within an attribute, looks for whether it is a - /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from - /// its expansion. - crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> { - mi.meta_item_list().and_then(|list| { - for meta in list { - if meta.has_name(sym::include) { - // the actual compiled `#[doc(include="filename")]` gets expanded to - // `#[doc(include(file="filename", contents="file contents")]` so we need to - // look for that instead - return meta.meta_item_list().and_then(|list| { - let mut filename: Option = None; - let mut contents: Option = None; - - for it in list { - if it.has_name(sym::file) { - if let Some(name) = it.value_str() { - filename = Some(name); - } - } else if it.has_name(sym::contents) { - if let Some(docs) = it.value_str() { - contents = Some(docs); - } - } - } - - if let (Some(filename), Some(contents)) = (filename, contents) { - Some((filename, contents)) - } else { - None - } - }); - } - } - - None - }) - } - crate fn has_doc_flag(&self, flag: Symbol) -> bool { for attr in &self.other_attrs { if !attr.has_name(sym::doc) { @@ -1050,18 +998,9 @@ impl Attributes { let mut doc_strings: Vec = vec![]; let mut doc_line = 0; - fn update_need_backline(doc_strings: &mut Vec, frag: &DocFragment) { + fn update_need_backline(doc_strings: &mut Vec) { if let Some(prev) = doc_strings.last_mut() { - if matches!(prev.kind, DocFragmentKind::Include { .. }) - || prev.kind != frag.kind - || prev.parent_module != frag.parent_module - { - // add a newline for extra padding between segments - prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc - || prev.kind == DocFragmentKind::RawDoc - } else { - prev.need_backline = true; - } + prev.need_backline = true; } } @@ -1087,31 +1026,12 @@ impl Attributes { indent: 0, }; - update_need_backline(&mut doc_strings, &frag); + update_need_backline(&mut doc_strings); doc_strings.push(frag); None } else { - if attr.has_name(sym::doc) { - if let Some(mi) = attr.meta() { - if let Some((filename, contents)) = Attributes::extract_include(&mi) { - let line = doc_line; - doc_line += contents.as_str().lines().count(); - let frag = DocFragment { - line, - span: attr.span, - doc: contents, - kind: DocFragmentKind::Include { filename }, - parent_module, - need_backline: false, - indent: 0, - }; - update_need_backline(&mut doc_strings, &frag); - doc_strings.push(frag); - } - } - } Some(attr.clone()) } }; @@ -1137,10 +1057,7 @@ impl Attributes { let mut out = String::new(); add_doc_fragment(&mut out, &ori); while let Some(new_frag) = iter.next() { - if matches!(ori.kind, DocFragmentKind::Include { .. }) - || new_frag.kind != ori.kind - || new_frag.parent_module != ori.parent_module - { + if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module { break; } add_doc_fragment(&mut out, &new_frag); diff --git a/src/test/run-make-fulldeps/include_bytes_deps/main.rs b/src/test/run-make-fulldeps/include_bytes_deps/main.rs index 00ad0eb8d5072..2fd55699d44dd 100644 --- a/src/test/run-make-fulldeps/include_bytes_deps/main.rs +++ b/src/test/run-make-fulldeps/include_bytes_deps/main.rs @@ -1,6 +1,4 @@ -#![feature(external_doc)] - -#[doc(include="input.md")] +#[doc = include_str!("input.md")] pub struct SomeStruct; pub fn main() { diff --git a/src/test/run-make-fulldeps/save-analysis/foo.rs b/src/test/run-make-fulldeps/save-analysis/foo.rs index 483eeed0b39f0..dd70675032f77 100644 --- a/src/test/run-make-fulldeps/save-analysis/foo.rs +++ b/src/test/run-make-fulldeps/save-analysis/foo.rs @@ -2,7 +2,6 @@ #![feature(box_syntax)] #![feature(rustc_private)] #![feature(associated_type_defaults)] -#![feature(external_doc)] extern crate rustc_graphviz; // A simple rust project @@ -454,9 +453,9 @@ impl Iterator for SilenceGenerator { } } +#[doc = include_str!("extra-docs.md")] +struct StructWithDocs; + trait Foo { type Bar = FrameBuffer; } - -#[doc(include = "extra-docs.md")] -struct StructWithDocs; diff --git a/src/test/rustdoc-ui/doc-include-suggestion.rs b/src/test/rustdoc-ui/doc-include-suggestion.rs new file mode 100644 index 0000000000000..0c01007355146 --- /dev/null +++ b/src/test/rustdoc-ui/doc-include-suggestion.rs @@ -0,0 +1,10 @@ +// check-pass + +#[doc(include = "external-cross-doc.md")] +//~^ WARNING unknown `doc` attribute `include` +//~| HELP use `doc = include_str!` instead +// FIXME(#85497): make this a deny instead so it's more clear what's happening +//~| NOTE on by default +//~| WARNING previously accepted +//~| NOTE see issue #82730 +pub struct NeedMoreDocs; diff --git a/src/test/rustdoc-ui/doc-include-suggestion.stderr b/src/test/rustdoc-ui/doc-include-suggestion.stderr new file mode 100644 index 0000000000000..870b7efa2ac95 --- /dev/null +++ b/src/test/rustdoc-ui/doc-include-suggestion.stderr @@ -0,0 +1,12 @@ +warning: unknown `doc` attribute `include` + --> $DIR/doc-include-suggestion.rs:3:7 + | +LL | #[doc(include = "external-cross-doc.md")] + | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]` + | + = note: `#[warn(invalid_doc_attributes)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +warning: 1 warning emitted + diff --git a/src/test/rustdoc/auxiliary/external-cross-doc.md b/src/test/rustdoc/auxiliary/external-cross-doc.md index 8b4e6edc69997..d3c8532655930 100644 --- a/src/test/rustdoc/auxiliary/external-cross-doc.md +++ b/src/test/rustdoc/auxiliary/external-cross-doc.md @@ -1,4 +1,4 @@ # Cross-crate imported docs -This file is to make sure `#[doc(include="file.md")]` works when you re-export an item with included +This file is to make sure `#[doc = include_str!("file.md")]` works when you re-export an item with included docs. diff --git a/src/test/rustdoc/auxiliary/external-cross.rs b/src/test/rustdoc/auxiliary/external-cross.rs index 473d4ec99f037..5de63cdabc6f9 100644 --- a/src/test/rustdoc/auxiliary/external-cross.rs +++ b/src/test/rustdoc/auxiliary/external-cross.rs @@ -1,5 +1,3 @@ -#![feature(external_doc)] -#![deny(missing_doc)] - -#[doc(include="external-cross-doc.md")] +#[deny(missing_docs)] +#[doc = include_str!("external-cross-doc.md")] pub struct NeedMoreDocs; diff --git a/src/test/rustdoc/auxiliary/external-doc.md b/src/test/rustdoc/auxiliary/external-doc.md index 38478c1635a17..babde0a05ad2f 100644 --- a/src/test/rustdoc/auxiliary/external-doc.md +++ b/src/test/rustdoc/auxiliary/external-doc.md @@ -1,3 +1,3 @@ # External Docs -This file is here to test the `#[doc(include="file")]` attribute. +This file is here to test the `#[doc = include_str!("file")]` attribute. diff --git a/src/test/rustdoc/external-doc.rs b/src/test/rustdoc/external-doc.rs index 0dadca551a9ff..fc29cb252e26c 100644 --- a/src/test/rustdoc/external-doc.rs +++ b/src/test/rustdoc/external-doc.rs @@ -1,12 +1,3 @@ -#![feature(external_doc)] - -// @has external_doc/struct.CanHasDocs.html -// @has - '//h1' 'External Docs' -// @has - '//h2' 'Inline Docs' -#[doc(include = "auxiliary/external-doc.md")] -/// ## Inline Docs -pub struct CanHasDocs; - // @has external_doc/struct.IncludeStrDocs.html // @has - '//h1' 'External Docs' // @has - '//h2' 'Inline Docs' diff --git a/src/test/rustdoc/unindent.rs b/src/test/rustdoc/unindent.rs index d10e1ec89c59e..372af5f4672a7 100644 --- a/src/test/rustdoc/unindent.rs +++ b/src/test/rustdoc/unindent.rs @@ -1,5 +1,3 @@ -#![feature(external_doc)] - #![crate_name = "foo"] // @has foo/struct.Example.html @@ -51,7 +49,7 @@ pub struct I; // @matches - '//div[@class="docblock"]/p' '(?m)a\nno whitespace\nJust some text.\Z' ///a ///no whitespace -#[doc(include = "unindent.md")] +#[doc = include_str!("unindent.md")] pub struct J; // @has foo/struct.K.html @@ -60,5 +58,5 @@ pub struct J; /// /// 4 whitespaces! /// -#[doc(include = "unindent.md")] +#[doc = include_str!("unindent.md")] pub struct K; diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs deleted file mode 100644 index 4e89f7464da49..0000000000000 --- a/src/test/ui/extern/external-doc-error.rs +++ /dev/null @@ -1,31 +0,0 @@ -// normalize-stderr-test: "not-a-file.md:.*\(" -> "not-a-file.md: $$FILE_NOT_FOUND_MSG (" - -#![feature(external_doc)] - -#[doc(include = "not-a-file.md")] -pub struct SomeStruct; //~^ ERROR couldn't read - -#[doc(include = "auxiliary/invalid-utf8.txt")] -pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file - -#[doc(include)] -pub struct MissingPath; //~^ ERROR expected path - //~| HELP provide a file path with `=` - //~| SUGGESTION include = "" - -#[doc(include("../README.md"))] -pub struct InvalidPathSyntax; //~^ ERROR expected path - //~| HELP provide a file path with `=` - //~| SUGGESTION include = "../README.md" - -#[doc(include = 123)] -pub struct InvalidPathType; //~^ ERROR expected path - //~| HELP provide a file path with `=` - //~| SUGGESTION include = "" - -#[doc(include(123))] -pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path - //~| HELP provide a file path with `=` - //~| SUGGESTION include = "" - -fn main() {} diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr deleted file mode 100644 index b180cd66c5269..0000000000000 --- a/src/test/ui/extern/external-doc-error.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/external-doc-error.rs:5:17 - | -LL | #[doc(include = "not-a-file.md")] - | ^^^^^^^^^^^^^^^ couldn't read file - -error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file - --> $DIR/external-doc-error.rs:8:17 - | -LL | #[doc(include = "auxiliary/invalid-utf8.txt")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8 - -error: expected path to external documentation - --> $DIR/external-doc-error.rs:11:7 - | -LL | #[doc(include)] - | ^^^^^^^ help: provide a file path with `=`: `include = ""` - -error: expected path to external documentation - --> $DIR/external-doc-error.rs:16:7 - | -LL | #[doc(include("../README.md"))] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"` - -error: expected path to external documentation - --> $DIR/external-doc-error.rs:21:7 - | -LL | #[doc(include = 123)] - | ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = ""` - -error: expected path to external documentation - --> $DIR/external-doc-error.rs:26:7 - | -LL | #[doc(include(123))] - | ^^^^^^^^^^^^ help: provide a file path with `=`: `include = ""` - -error: aborting due to 6 previous errors - diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs deleted file mode 100644 index 4e6e293846c6e..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-external_doc.rs +++ /dev/null @@ -1,3 +0,0 @@ -#[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental - //~| ERROR: `#[doc(include)]` is experimental -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr deleted file mode 100644 index bd2aefe90c183..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: `#[doc(include)]` is experimental - --> $DIR/feature-gate-external_doc.rs:1:1 - | -LL | #[doc(include="asdf.md")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #44732 for more information - = help: add `#![feature(external_doc)]` to the crate attributes to enable - -error[E0658]: `#[doc(include)]` is experimental - --> $DIR/feature-gate-external_doc.rs:1:1 - | -LL | #[doc(include="asdf.md")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #44732 for more information - = help: add `#![feature(external_doc)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index ec1572c26c262..a46a7407df0ce 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -7,8 +7,7 @@ use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint; -use if_chain::if_chain; -use rustc_ast::ast::{self, MetaItem, MetaItemKind}; +use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; @@ -56,20 +55,6 @@ impl MissingDoc { *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") } - fn has_include(meta: Option) -> bool { - if_chain! { - if let Some(meta) = meta; - if let MetaItemKind::List(list) = meta.kind; - if let Some(meta) = list.get(0); - if let Some(name) = meta.ident(); - then { - name.name == sym::include - } else { - false - } - } - } - fn check_missing_docs_attrs( &self, cx: &LateContext<'_>, @@ -95,7 +80,7 @@ impl MissingDoc { let has_doc = attrs .iter() - .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())); + .any(|a| a.doc_str().is_some()); if !has_doc { span_lint( cx, diff --git a/src/tools/clippy/tests/ui/missing-doc-crate.rs b/src/tools/clippy/tests/ui/missing-doc-crate.rs index 04711f864886b..e00c7fbfed157 100644 --- a/src/tools/clippy/tests/ui/missing-doc-crate.rs +++ b/src/tools/clippy/tests/ui/missing-doc-crate.rs @@ -1,5 +1,4 @@ #![warn(clippy::missing_docs_in_private_items)] -#![feature(external_doc)] -#![doc(include = "../../README.md")] +#![doc = include_str!("../../README.md")] fn main() {}