diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 71bbae1161b4b..a8c61d53346de 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -5,7 +5,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; use rustc_ast_pretty::pprust; -use rustc_expand::base::{ExtCtxt, ResolverExpand}; +use rustc_expand::base::{parse_macro_name_and_helper_attrs, ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_session::Session; use rustc_span::hygiene::AstPass; @@ -109,86 +109,17 @@ impl<'a> CollectProcMacros<'a> { } fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { - // Once we've located the `#[proc_macro_derive]` attribute, verify - // that it's of the form `#[proc_macro_derive(Foo)]` or - // `#[proc_macro_derive(Foo, attributes(A, ..))]` - let list = match attr.meta_item_list() { - Some(list) => list, - None => return, - }; - if list.len() != 1 && list.len() != 2 { - self.handler.span_err(attr.span, "attribute must have either one or two arguments"); - return; - } - let trait_attr = match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(list[0].span(), "not a meta item"); - return; - } - }; - let trait_ident = match trait_attr.ident() { - Some(trait_ident) if trait_attr.is_word() => trait_ident, - _ => { - self.handler.span_err(trait_attr.span, "must only be one word"); - return; - } - }; - - if !trait_ident.name.can_be_raw() { - self.handler.span_err( - trait_attr.span, - &format!("`{}` cannot be a name of derive macro", trait_ident), - ); - } - - let attributes_attr = list.get(1); - let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { - if !attr.has_name(sym::attributes) { - self.handler.span_err(attr.span(), "second argument must be `attributes`") - } - attr.meta_item_list() - .unwrap_or_else(|| { - self.handler - .span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); - &[] - }) - .iter() - .filter_map(|attr| { - let attr = match attr.meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(attr.span(), "not a meta item"); - return None; - } - }; - - let ident = match attr.ident() { - Some(ident) if attr.is_word() => ident, - _ => { - self.handler.span_err(attr.span, "must only be one word"); - return None; - } - }; - if !ident.name.can_be_raw() { - self.handler.span_err( - attr.span, - &format!("`{}` cannot be a name of derive helper attribute", ident), - ); - } - - Some(ident.name) - }) - .collect() - } else { - Vec::new() - }; + let (trait_name, proc_attrs) = + match parse_macro_name_and_helper_attrs(self.handler, attr, "derive") { + Some(name_and_attrs) => name_and_attrs, + None => return, + }; if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Derive(ProcMacroDerive { id: item.id, span: item.span, - trait_name: trait_ident.name, + trait_name, function_name: item.ident, attrs: proc_attrs, })); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b3e52502b0739..0183add495777 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -745,9 +745,17 @@ impl SyntaxExtension { } } - let builtin_name = sess + let (builtin_name, helper_attrs) = sess .find_by_name(attrs, sym::rustc_builtin_macro) - .map(|a| a.value_str().unwrap_or(name)); + .map(|attr| { + // Override `helper_attrs` passed above if it's a built-in macro, + // marking `proc_macro_derive` macros as built-in is not a realistic use case. + parse_macro_name_and_helper_attrs(sess.diagnostic(), attr, "built-in").map_or_else( + || (Some(name), Vec::new()), + |(name, helper_attrs)| (Some(name), helper_attrs), + ) + }) + .unwrap_or_else(|| (None, helper_attrs)); let (stability, const_stability) = attr::find_stability(&sess, attrs, span); if let Some((_, sp)) = const_stability { sess.parse_sess @@ -1213,6 +1221,88 @@ pub fn get_exprs_from_tts( Some(es) } +pub fn parse_macro_name_and_helper_attrs( + diag: &rustc_errors::Handler, + attr: &Attribute, + descr: &str, +) -> Option<(Symbol, Vec)> { + // Once we've located the `#[proc_macro_derive]` attribute, verify + // that it's of the form `#[proc_macro_derive(Foo)]` or + // `#[proc_macro_derive(Foo, attributes(A, ..))]` + let list = match attr.meta_item_list() { + Some(list) => list, + None => return None, + }; + if list.len() != 1 && list.len() != 2 { + diag.span_err(attr.span, "attribute must have either one or two arguments"); + return None; + } + let trait_attr = match list[0].meta_item() { + Some(meta_item) => meta_item, + _ => { + diag.span_err(list[0].span(), "not a meta item"); + return None; + } + }; + let trait_ident = match trait_attr.ident() { + Some(trait_ident) if trait_attr.is_word() => trait_ident, + _ => { + diag.span_err(trait_attr.span, "must only be one word"); + return None; + } + }; + + if !trait_ident.name.can_be_raw() { + diag.span_err( + trait_attr.span, + &format!("`{}` cannot be a name of {} macro", trait_ident, descr), + ); + } + + let attributes_attr = list.get(1); + let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { + if !attr.has_name(sym::attributes) { + diag.span_err(attr.span(), "second argument must be `attributes`") + } + attr.meta_item_list() + .unwrap_or_else(|| { + diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); + &[] + }) + .iter() + .filter_map(|attr| { + let attr = match attr.meta_item() { + Some(meta_item) => meta_item, + _ => { + diag.span_err(attr.span(), "not a meta item"); + return None; + } + }; + + let ident = match attr.ident() { + Some(ident) if attr.is_word() => ident, + _ => { + diag.span_err(attr.span, "must only be one word"); + return None; + } + }; + if !ident.name.can_be_raw() { + diag.span_err( + attr.span, + &format!("`{}` cannot be a name of derive helper attribute", ident), + ); + } + + Some(ident.name) + }) + .collect() + } else { + Vec::new() + }; + + Some((trait_ident.name, proc_attrs)) +} + /// This nonterminal looks like some specific enums from /// `proc-macro-hack` and `procedural-masquerade` crates. /// We need to maintain some special pretty-printing behavior for them due to incorrect diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 77d8f0f920c14..b1c725ecd85c8 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -448,7 +448,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Macro related: // ========================================================================== - rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL), + rustc_attr!( + rustc_builtin_macro, AssumedUsed, + template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), + IMPL_DETAIL, + ), rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, AssumedUsed, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index e568b5ca50110..958a4ab68020a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -18,7 +18,7 @@ use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::middle; -use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; +use rustc_middle::middle::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_mir as mir; @@ -860,11 +860,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().proc_macro_decls_static(()) }); - let cstore = tcx - .cstore_as_any() - .downcast_ref::() - .expect("`tcx.cstore` is not a `CStore`"); - cstore.report_unused_deps(tcx); + CStore::from_tcx(tcx).report_unused_deps(tcx); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 250af3c6e89cb..70d29f9d7caa8 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -130,7 +130,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { } impl CStore { - crate fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { + pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { tcx.cstore_as_any().downcast_ref::().expect("`tcx.cstore` is not a `CStore`") } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index d96034c951c6c..ce8dfeae076e6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -5,7 +5,6 @@ use crate::rmeta::encoder; use rustc_ast as ast; use rustc_data_structures::stable_map::FxHashMap; -use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -369,6 +368,7 @@ pub fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, + crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()), ..*providers }; @@ -451,6 +451,16 @@ impl CStore { self.get_crate_data(def_id.krate).get_span(def_id.index, sess) } + pub fn def_kind(&self, def: DefId) -> DefKind { + self.get_crate_data(def.krate).def_kind(def.index) + } + + pub fn crates_untracked(&self) -> Vec { + let mut result = vec![]; + self.iter_crate_data(|cnum, _| result.push(cnum)); + result + } + pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes } @@ -485,18 +495,14 @@ impl CrateStore for CStore { self } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { + fn crate_name(&self, cnum: CrateNum) -> Symbol { self.get_crate_data(cnum).root.name } - fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId { + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId { self.get_crate_data(cnum).root.stable_crate_id } - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { - self.get_crate_data(cnum).root.hash - } - /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. @@ -504,10 +510,6 @@ impl CrateStore for CStore { self.get_crate_data(def.krate).def_key(def.index) } - fn def_kind(&self, def: DefId) -> DefKind { - self.get_crate_data(def.krate).def_kind(def.index) - } - fn def_path(&self, def: DefId) -> DefPath { self.get_crate_data(def.krate).def_path(def.index) } @@ -526,12 +528,6 @@ impl CrateStore for CStore { self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash) } - fn crates_untracked(&self) -> Vec { - let mut result = vec![]; - self.iter_crate_data(|cnum, _| result.push(cnum)); - result - } - fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata { encoder::encode_metadata(tcx) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 602e1fd822c02..5c7d84e2bc97f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1061,10 +1061,7 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { - reexports, - expansion: tcx.resolutions(()).definitions.expansion_that_defined(local_def_id), - }; + let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }; record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); if self.is_proc_macro { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5c32c0fdb6cc8..ae53f1ac3bb49 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,7 +1,6 @@ use self::collector::NodeCollector; use crate::hir::{AttributeMap, IndexedHir}; -use crate::middle::cstore::CrateStore; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; @@ -991,7 +990,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { }, ); - let upstream_crates = upstream_crates(&*tcx.untracked_resolutions.cstore); + let upstream_crates = upstream_crates(tcx); // We hash the final, remapped names of all local source files so we // don't have to include the path prefix remapping commandline args. @@ -1021,13 +1020,13 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { Svh::new(crate_hash.to_smaller_hash()) } -fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> { - let mut upstream_crates: Vec<_> = cstore - .crates_untracked() +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { + let mut upstream_crates: Vec<_> = tcx + .crates(()) .iter() .map(|&cnum| { - let stable_crate_id = cstore.stable_crate_id_untracked(cnum); - let hash = cstore.crate_hash_untracked(cnum); + let stable_crate_id = tcx.resolutions(()).cstore.stable_crate_id(cnum); + let hash = tcx.crate_hash(cnum); (stable_crate_id, hash) }) .collect(); diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index fcd4988635b07..7efe8e061e885 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -5,9 +5,7 @@ use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, MetadataRef}; -use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_macros::HashStable; @@ -190,11 +188,19 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; pub trait CrateStore: std::fmt::Debug { fn as_any(&self) -> &dyn Any; - // resolve + // Foreign definitions. + // This information is safe to access, since it's hashed as part of the DefPathHash, which incr. + // comp. uses to identify a DefId. fn def_key(&self, def: DefId) -> DefKey; - fn def_kind(&self, def: DefId) -> DefKind; fn def_path(&self, def: DefId) -> DefPath; fn def_path_hash(&self, def: DefId) -> DefPathHash; + + // This information is safe to access, since it's hashed as part of the StableCrateId, which + // incr. comp. uses to identify a CrateNum. + fn crate_name(&self, cnum: CrateNum) -> Symbol; + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId; + + /// Fetch a DefId from a DefPathHash for a foreign crate. fn def_path_hash_to_def_id( &self, cnum: CrateNum, @@ -202,15 +208,6 @@ pub trait CrateStore: std::fmt::Debug { hash: DefPathHash, ) -> Option; - // "queries" used in resolve that aren't tracked for incremental compilation - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; - fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId; - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; - - // This is basically a 1-based range of ints, which is a little - // silly - I may fix that. - fn crates_untracked(&self) -> Vec; - // utility functions fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bc471aff2d02e..80c4ff2ae5d99 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -213,6 +213,8 @@ rustc_queries! { } query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + // This query reads from untracked data in definitions. + eval_always desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } } @@ -1446,6 +1448,7 @@ rustc_queries! { desc { "calculating the stability index for the local crate" } } query crates(_: ()) -> &'tcx [CrateNum] { + eval_always desc { "fetching all foreign CrateNum instances" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1afeb4a138f9d..f52686c9b5f2e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1277,7 +1277,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.untracked_resolutions.cstore.stable_crate_id_untracked(crate_num) + self.untracked_resolutions.cstore.stable_crate_id(crate_num) } } @@ -1290,10 +1290,7 @@ impl<'tcx> TyCtxt<'tcx> { (self.crate_name, self.sess.local_stable_crate_id()) } else { let cstore = &self.untracked_resolutions.cstore; - ( - cstore.crate_name_untracked(def_id.krate), - cstore.stable_crate_id_untracked(def_id.krate), - ) + (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; format!( @@ -2831,8 +2828,6 @@ pub fn provide(providers: &mut ty::query::Providers) { }; providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); - providers.crates = - |tcx, ()| tcx.arena.alloc_slice(&tcx.resolutions(()).cstore.crates_untracked()); providers.output_filenames = |tcx, ()| tcx.output_filenames.clone(); providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index f91bf0cbab727..35e7688fbe45a 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -128,7 +128,7 @@ impl<'a> Resolver<'a> { let (name, parent) = if def_id.index == CRATE_DEF_INDEX { // This is the crate root - (self.cstore().crate_name_untracked(def_id.krate), None) + (self.cstore().crate_name(def_id.krate), None) } else { let def_key = self.cstore().def_key(def_id); let name = def_key diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7eb65483b99e7..7d22bfedb93b9 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1,6 +1,7 @@ #[doc = include_str!("panic.md")] #[macro_export] -#[rustc_builtin_macro = "core_panic"] +#[cfg_attr(bootstrap, rustc_builtin_macro = "core_panic")] +#[cfg_attr(not(bootstrap), rustc_builtin_macro(core_panic))] #[allow_internal_unstable(edition_panic)] #[stable(feature = "core", since = "1.6.0")] #[rustc_diagnostic_item = "core_panic_macro"] diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index b2c5df5410dca..7afe52a3fd693 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -6,7 +6,8 @@ #[doc = include_str!("../../core/src/macros/panic.md")] #[macro_export] -#[rustc_builtin_macro = "std_panic"] +#[cfg_attr(bootstrap, rustc_builtin_macro = "std_panic")] +#[cfg_attr(not(bootstrap), rustc_builtin_macro(std_panic))] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(edition_panic)] #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")] diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 6dcf0bdcba43f..779b301ff618f 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.4.1 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.4.2 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index cd914f05e680c..c5ca396e72029 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -167,11 +167,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { test_args.insert(0, "rustdoctest".to_string()); - testing::test_main( - &test_args, - tests, - Some(testing::Options::new().display_output(display_warnings)), - ); + test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings))); // Collect and warn about unused externs, but only if we've gotten // reports for each doctest @@ -769,7 +765,7 @@ crate trait Tester { } crate struct Collector { - crate tests: Vec, + crate tests: Vec, // The name of the test displayed to the user, separated by `::`. // @@ -930,22 +926,22 @@ impl Tester for Collector { }; debug!("creating test {}: {}", name, test); - self.tests.push(testing::TestDescAndFn { - desc: testing::TestDesc { - name: testing::DynTestName(name), + self.tests.push(test::TestDescAndFn { + desc: test::TestDesc { + name: test::DynTestName(name), ignore: match config.ignore { Ignore::All => true, Ignore::None => false, Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, // compiler failures are test failures - should_panic: testing::ShouldPanic::No, + should_panic: test::ShouldPanic::No, allow_fail: config.allow_fail, compile_fail: config.compile_fail, no_run, - test_type: testing::TestType::DocTest, + test_type: test::TestType::DocTest, }, - testfn: testing::DynTestFn(box move || { + testfn: test::DynTestFn(box move || { let report_unused_externs = |uext| { unused_externs.lock().unwrap().push(uext); }; diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9fff508165a10..3b599e4997a4b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -33,6 +33,7 @@ use std::str; use crate::clean::RenderedLink; use crate::doctest; +use crate::html::escape::Escape; use crate::html::highlight; use crate::html::toc::TocBuilder; @@ -207,26 +208,11 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let should_panic; let ignore; let edition; - if let Some(Event::Start(Tag::CodeBlock(kind))) = event { - let parse_result = match kind { - CodeBlockKind::Fenced(ref lang) => { - LangString::parse_without_check(&lang, self.check_error_codes, false) - } - CodeBlockKind::Indented => Default::default(), - }; - if !parse_result.rust { - return Some(Event::Start(Tag::CodeBlock(kind))); - } - compile_fail = parse_result.compile_fail; - should_panic = parse_result.should_panic; - ignore = parse_result.ignore; - edition = parse_result.edition; + let kind = if let Some(Event::Start(Tag::CodeBlock(kind))) = event { + kind } else { return event; - } - - let explicit_edition = edition.is_some(); - let edition = edition.unwrap_or(self.edition); + }; let mut origtext = String::new(); for event in &mut self.inner { @@ -241,6 +227,35 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); let text = lines.collect::>>().join("\n"); + let parse_result = match kind { + CodeBlockKind::Fenced(ref lang) => { + let parse_result = + LangString::parse_without_check(&lang, self.check_error_codes, false); + if !parse_result.rust { + return Some(Event::Html( + format!( + "
\ + {}\ +
", + format!(" class=\"language-{}\"", lang), + Escape(&text), + ) + .into(), + )); + } + parse_result + } + CodeBlockKind::Indented => Default::default(), + }; + + compile_fail = parse_result.compile_fail; + should_panic = parse_result.should_panic; + ignore = parse_result.ignore; + edition = parse_result.edition; + + let explicit_edition = edition.is_some(); + let edition = edition.unwrap_or(self.edition); + let playground_button = self.playground.as_ref().and_then(|playground| { let krate = &playground.crate_name; let url = &playground.url; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 66dfd2fac84c6..208e8f723f407 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -435,7 +435,7 @@ nav.sub { border-bottom-left-radius: 5px; } -.rustdoc:not(.source) .example-wrap > pre.rust { +.rustdoc:not(.source) .example-wrap > pre:not(.line-number) { width: 100%; overflow-x: auto; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 9da3fe07adea0..8296c3f91ca3b 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -34,7 +34,7 @@ h4 { background: rgba(0, 0, 0, 0); } -code { +.docblock code { color: #ffb454; } h3 > code, h4 > code, h5 > code { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bc635190f4281..d4d87819c0d7a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -53,11 +53,11 @@ extern crate rustc_parse; extern crate rustc_passes; extern crate rustc_resolve; extern crate rustc_session; -extern crate rustc_span as rustc_span; +extern crate rustc_span; extern crate rustc_target; extern crate rustc_trait_selection; extern crate rustc_typeck; -extern crate test as testing; +extern crate test; #[cfg(feature = "jemalloc")] extern crate tikv_jemalloc_sys; diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 5da3a75e87631..45966c0058df4 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -136,10 +136,10 @@ crate fn test(mut options: Options) -> Result<(), String> { find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None); options.test_args.insert(0, "rustdoctest".to_string()); - testing::test_main( + test::test_main( &options.test_args, collector.tests, - Some(testing::Options::new().display_output(options.display_warnings)), + Some(test::Options::new().display_output(options.display_warnings)), ); Ok(()) } diff --git a/src/test/rustdoc-gui/ayu-code-tag-colors.goml b/src/test/rustdoc-gui/ayu-code-tag-colors.goml new file mode 100644 index 0000000000000..50af36fa3d641 --- /dev/null +++ b/src/test/rustdoc-gui/ayu-code-tag-colors.goml @@ -0,0 +1,13 @@ +// The ayu theme has a different color for the "" tags in the doc blocks. We need to +// check that the rule isn't applied on other "" elements. +goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html +// We need to show the text, otherwise the colors aren't "computed" by the web browser. +show-text: true +// We set the theme to ayu. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} +// We reload to get the text appearing and the theme applied. +reload: + +assert-css: (".docblock code", {"color": "rgb(255, 180, 84)"}, ALL) +// It includes variants and the "titles" as well (for example: "impl RefUnwindSafe for AnEnum"). +assert-css: ("div:not(.docblock) > code", {"color": "rgb(197, 197, 197)"}, ALL) diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml new file mode 100644 index 0000000000000..ee4dad444e932 --- /dev/null +++ b/src/test/rustdoc-gui/code-blocks-overflow.goml @@ -0,0 +1,8 @@ +// This test ensures that codeblocks content don't overflow. +goto: file://|DOC_PATH|/lib2/sub_mod/struct.Foo.html +size: (1080, 600) +// There should be two codeblocks: a rust one and a non-rust one. +assert-count: (".docblock > .example-wrap", 2) +assert: ".docblock > .example-wrap > .language-txt" +assert: ".docblock > .example-wrap > .rust-example-rendered" +assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL) diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 72ef3cbd2026d..ec8ab339e2804 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + pub mod module { pub mod sub_module { pub mod sub_sub_module { @@ -32,4 +34,16 @@ impl Trait for Foo { const Y: u32 = 0; } + impl implementors::Whatever for Foo {} + +pub mod sub_mod { + /// ```txt + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// ``` + /// + /// ``` + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// ``` + pub struct Foo; +} diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index 1b9f652120e94..85dd8805fbc4c 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -96,6 +96,7 @@ pub fn check_list_code_block() {} #[doc(cfg(unix))] pub fn replaced_function() {} +/// Some doc with `code`! pub enum AnEnum { WithVariants { and: usize, sub: usize, variants: usize }, } diff --git a/src/test/ui/deriving/deriving-with-helper.rs b/src/test/ui/deriving/deriving-with-helper.rs new file mode 100644 index 0000000000000..ea74a15624c60 --- /dev/null +++ b/src/test/ui/deriving/deriving-with-helper.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: --crate-type=lib + +#![feature(decl_macro)] +#![feature(lang_items)] +#![feature(no_core)] +#![feature(rustc_attrs)] + +#![no_core] + +#[rustc_builtin_macro] +macro derive() {} + +#[rustc_builtin_macro(Default, attributes(default))] +macro Default() {} + +mod default { + pub trait Default { + fn default() -> Self; + } + + impl Default for u8 { + fn default() -> u8 { + 0 + } + } +} + +#[lang = "sized"] +trait Sized {} + +#[derive(Default)] +struct S { + #[default] // OK + field: u8, +}