Auto merge of #87133 - GuillaumeGomez:rollup-pfz9jbk, r=GuillaumeGomez

Rollup of 6 pull requests

Successful merges:

 - #87027 (expand: Support helper attributes for built-in derive macros)
 - #87056 (Fix codeblocks overflow)
 - #87117 (Shrink the CrateStore dynamic interface.)
 - #87120 (rustdoc: Remove unnecessary `extern crate` aliases)
 - #87125 (Fix Ayu theme `<code>` color)
 - #87130 (Update browser-ui-test package version)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-07-14 18:36:44 +00:00
commit e87188c252
26 changed files with 267 additions and 174 deletions

View File

@ -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,
}));

View File

@ -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<Symbol>)> {
// 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

View File

@ -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,

View File

@ -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::<CStore>()
.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, _)| {

View File

@ -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::<CStore>().expect("`tcx.cstore` is not a `CStore`")
}

View File

@ -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<CrateNum> {
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<CrateNum> {
let mut result = vec![];
self.iter_crate_data(|cnum, _| result.push(cnum));
result
}
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
encoder::encode_metadata(tcx)
}

View File

@ -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 {

View File

@ -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();

View File

@ -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<DefId>;
// "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<CrateNum>;
// utility functions
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
}

View File

@ -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" }
}

View File

@ -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| {

View File

@ -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

View File

@ -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"]

View File

@ -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")]

View File

@ -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 \

View File

@ -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<testing::TestDescAndFn>,
crate tests: Vec<test::TestDescAndFn>,
// 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);
};

View File

@ -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<Item = Event<'a>>> 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<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
let text = lines.collect::<Vec<Cow<'_, str>>>().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!(
"<div class=\"example-wrap\">\
<pre{}>{}</pre>\
</div>",
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;

View File

@ -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;
}

View File

@ -34,7 +34,7 @@ h4 {
background: rgba(0, 0, 0, 0);
}
code {
.docblock code {
color: #ffb454;
}
h3 > code, h4 > code, h5 > code {

View File

@ -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;

View File

@ -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(())
}

View File

@ -0,0 +1,13 @@
// The ayu theme has a different color for the "<code>" tags in the doc blocks. We need to
// check that the rule isn't applied on other "<code>" 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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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 },
}

View File

@ -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,
}