Auto merge of #110481 - matthiaskrgr:rollup-phkkgm9, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #109981 (Set commit information environment variables when building tools) - #110348 (Add list of supported disambiguators and suffixes for intra-doc links in the rustdoc book) - #110409 (Don't use `serde_json` to serialize a simple JSON object) - #110442 (Avoid including dry run steps in the build metrics) - #110450 (rustdoc: Fix invalid handling of nested items with `--document-private-items`) - #110461 (Use `Item::expect_*` and `ImplItem::expect_*` more) - #110465 (Assure everyone that `has_type_flags` is fast) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
74864fa496
27 changed files with 244 additions and 70 deletions
|
@ -3181,7 +3181,6 @@ dependencies = [
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
"serde_json",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
"stacker",
|
"stacker",
|
||||||
|
|
|
@ -138,12 +138,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
// Evaluate with the lifetimes in `params` in-scope.
|
// Evaluate with the lifetimes in `params` in-scope.
|
||||||
// This is used to track which lifetimes have already been defined,
|
// This is used to track which lifetimes have already been defined,
|
||||||
// and which need to be replicated when lowering an async fn.
|
// and which need to be replicated when lowering an async fn.
|
||||||
match parent_hir.node().expect_item().kind {
|
|
||||||
hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
|
if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
|
||||||
lctx.is_in_trait_impl = of_trait.is_some();
|
lctx.is_in_trait_impl = impl_.of_trait.is_some();
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
match ctxt {
|
match ctxt {
|
||||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
|
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
|
||||||
|
|
|
@ -21,7 +21,6 @@ rustc-hash = "1.1.0"
|
||||||
rustc_index = { path = "../rustc_index", package = "rustc_index" }
|
rustc_index = { path = "../rustc_index", package = "rustc_index" }
|
||||||
rustc_macros = { path = "../rustc_macros" }
|
rustc_macros = { path = "../rustc_macros" }
|
||||||
rustc_serialize = { path = "../rustc_serialize" }
|
rustc_serialize = { path = "../rustc_serialize" }
|
||||||
serde_json = "1.0.59"
|
|
||||||
smallvec = { version = "1.8.1", features = [
|
smallvec = { version = "1.8.1", features = [
|
||||||
"const_generics",
|
"const_generics",
|
||||||
"union",
|
"union",
|
||||||
|
|
|
@ -87,6 +87,7 @@ use crate::fx::FxHashMap;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::fmt::Display;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::intrinsics::unlikely;
|
use std::intrinsics::unlikely;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -97,7 +98,6 @@ use std::time::{Duration, Instant};
|
||||||
pub use measureme::EventId;
|
pub use measureme::EventId;
|
||||||
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
|
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use serde_json::json;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
|
@ -763,6 +763,31 @@ impl Drop for VerboseTimingGuard<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct JsonTimePassesEntry<'a> {
|
||||||
|
pass: &'a str,
|
||||||
|
time: f64,
|
||||||
|
start_rss: Option<usize>,
|
||||||
|
end_rss: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for JsonTimePassesEntry<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Self { pass: what, time, start_rss, end_rss } = self;
|
||||||
|
write!(f, r#"{{"pass":"{what}","time":{time},"rss_start":"#).unwrap();
|
||||||
|
match start_rss {
|
||||||
|
Some(rss) => write!(f, "{rss}")?,
|
||||||
|
None => write!(f, "null")?,
|
||||||
|
}
|
||||||
|
write!(f, r#","rss_end":"#)?;
|
||||||
|
match end_rss {
|
||||||
|
Some(rss) => write!(f, "{rss}")?,
|
||||||
|
None => write!(f, "null")?,
|
||||||
|
}
|
||||||
|
write!(f, "}}")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_time_passes_entry(
|
pub fn print_time_passes_entry(
|
||||||
what: &str,
|
what: &str,
|
||||||
dur: Duration,
|
dur: Duration,
|
||||||
|
@ -772,13 +797,10 @@ pub fn print_time_passes_entry(
|
||||||
) {
|
) {
|
||||||
match format {
|
match format {
|
||||||
TimePassesFormat::Json => {
|
TimePassesFormat::Json => {
|
||||||
let json = json!({
|
let entry =
|
||||||
"pass": what,
|
JsonTimePassesEntry { pass: what, time: dur.as_secs_f64(), start_rss, end_rss };
|
||||||
"time": dur.as_secs_f64(),
|
|
||||||
"rss_start": start_rss,
|
eprintln!(r#"time: {entry}"#);
|
||||||
"rss_end": end_rss,
|
|
||||||
});
|
|
||||||
eprintln!("time: {json}");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TimePassesFormat::Text => (),
|
TimePassesFormat::Text => (),
|
||||||
|
@ -894,3 +916,6 @@ cfg_if! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
19
compiler/rustc_data_structures/src/profiling/tests.rs
Normal file
19
compiler/rustc_data_structures/src/profiling/tests.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use super::JsonTimePassesEntry;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_rss() {
|
||||||
|
let entry =
|
||||||
|
JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: Some(10), end_rss: Some(20) };
|
||||||
|
|
||||||
|
assert_eq!(entry.to_string(), r#"{"pass":"typeck","time":56.1,"rss_start":10,"rss_end":20}"#)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_rss() {
|
||||||
|
let entry = JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: None, end_rss: None };
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
entry.to_string(),
|
||||||
|
r#"{"pass":"typeck","time":56.1,"rss_start":null,"rss_end":null}"#
|
||||||
|
)
|
||||||
|
}
|
|
@ -3146,7 +3146,6 @@ impl<'hir> Item<'hir> {
|
||||||
(ty, gen)
|
(ty, gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
|
|
||||||
/// Expect an [`ItemKind::OpaqueTy`] or panic.
|
/// Expect an [`ItemKind::OpaqueTy`] or panic.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
|
pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
|
||||||
|
@ -3168,7 +3167,6 @@ impl<'hir> Item<'hir> {
|
||||||
(data, gen)
|
(data, gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
|
|
||||||
/// Expect an [`ItemKind::Union`] or panic.
|
/// Expect an [`ItemKind::Union`] or panic.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
|
pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
|
||||||
|
|
|
@ -74,10 +74,9 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||||
|
|
||||||
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
|
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
|
||||||
|
|
||||||
let span = match tcx.hir().expect_item(impl_did).kind {
|
let span = match tcx.hir().expect_item(impl_did).expect_impl() {
|
||||||
ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
|
hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
|
||||||
ItemKind::Impl(impl_) => impl_.self_ty.span,
|
hir::Impl { self_ty, .. } => self_ty.span,
|
||||||
_ => bug!("expected Copy impl item"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let cause = traits::ObligationCause::misc(span, impl_did);
|
let cause = traits::ObligationCause::misc(span, impl_did);
|
||||||
|
|
|
@ -462,10 +462,7 @@ fn foo(&self) -> Self::T { String::new() }
|
||||||
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
|
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
|
||||||
let opaque_local_def_id = def_id.as_local();
|
let opaque_local_def_id = def_id.as_local();
|
||||||
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
|
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
|
||||||
match &tcx.hir().expect_item(opaque_local_def_id).kind {
|
tcx.hir().expect_item(opaque_local_def_id).expect_opaque_ty()
|
||||||
hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
|
|
||||||
_ => bug!("The HirId comes from a `ty::Opaque`"),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -392,12 +392,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
/// defining scope.
|
/// defining scope.
|
||||||
#[instrument(skip(self), level = "trace", ret)]
|
#[instrument(skip(self), level = "trace", ret)]
|
||||||
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
|
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
|
||||||
match self.tcx.hir().expect_item(def_id).kind {
|
self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
|
||||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
|
|
||||||
ref itemkind => {
|
|
||||||
bug!("weird opaque type: {:?}, {:#?}", def_id, itemkind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1469,8 +1469,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
|
|
||||||
match impl_item.kind {
|
match impl_item.kind {
|
||||||
ty::AssocKind::Fn => {
|
ty::AssocKind::Fn => {
|
||||||
let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
|
let (sig, body) =
|
||||||
let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
|
self.tcx.hir().expect_impl_item(def_id.expect_local()).expect_fn();
|
||||||
self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
|
self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
|
||||||
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
|
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
|
||||||
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable
|
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable
|
||||||
|
|
|
@ -33,6 +33,14 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||||
|
// N.B. Even though this uses a visitor, the visitor does not actually
|
||||||
|
// recurse through the whole `TypeVisitable` implementor type.
|
||||||
|
//
|
||||||
|
// Instead it stops on the first "level", visiting types, regions,
|
||||||
|
// consts and predicates just fetches their type flags.
|
||||||
|
//
|
||||||
|
// Thus this is a lot faster than it might seem and should be
|
||||||
|
// optimized to a simple field access.
|
||||||
let res =
|
let res =
|
||||||
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
|
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
|
||||||
trace!(?self, ?flags, ?res, "has_type_flags");
|
trace!(?self, ?flags, ?res, "has_type_flags");
|
||||||
|
|
|
@ -2030,7 +2030,7 @@ impl<'a> Builder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "build-metrics")]
|
#[cfg(feature = "build-metrics")]
|
||||||
self.metrics.enter_step(&step);
|
self.metrics.enter_step(&step, self);
|
||||||
|
|
||||||
let (out, dur) = {
|
let (out, dur) = {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
@ -2056,7 +2056,7 @@ impl<'a> Builder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "build-metrics")]
|
#[cfg(feature = "build-metrics")]
|
||||||
self.metrics.exit_step();
|
self.metrics.exit_step(self);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stack = self.stack.borrow_mut();
|
let mut stack = self.stack.borrow_mut();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//! As this module requires additional dependencies not present during local builds, it's cfg'd
|
//! As this module requires additional dependencies not present during local builds, it's cfg'd
|
||||||
//! away whenever the `build.metrics` config option is not set to `true`.
|
//! away whenever the `build.metrics` config option is not set to `true`.
|
||||||
|
|
||||||
use crate::builder::Step;
|
use crate::builder::{Builder, Step};
|
||||||
use crate::util::t;
|
use crate::util::t;
|
||||||
use crate::Build;
|
use crate::Build;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
@ -33,7 +33,12 @@ impl BuildMetrics {
|
||||||
BuildMetrics { state }
|
BuildMetrics { state }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn enter_step<S: Step>(&self, step: &S) {
|
pub(crate) fn enter_step<S: Step>(&self, step: &S, builder: &Builder<'_>) {
|
||||||
|
// Do not record dry runs, as they'd be duplicates of the actual steps.
|
||||||
|
if builder.config.dry_run() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
|
|
||||||
// Consider all the stats gathered so far as the parent's.
|
// Consider all the stats gathered so far as the parent's.
|
||||||
|
@ -56,7 +61,12 @@ impl BuildMetrics {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn exit_step(&self) {
|
pub(crate) fn exit_step(&self, builder: &Builder<'_>) {
|
||||||
|
// Do not record dry runs, as they'd be duplicates of the actual steps.
|
||||||
|
if builder.config.dry_run() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
|
|
||||||
self.collect_stats(&mut *state);
|
self.collect_stats(&mut *state);
|
||||||
|
@ -74,7 +84,12 @@ impl BuildMetrics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome) {
|
pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome, builder: &Builder<'_>) {
|
||||||
|
// Do not record dry runs, as they'd be duplicates of the actual steps.
|
||||||
|
if builder.config.dry_run() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
state
|
state
|
||||||
.running_steps
|
.running_steps
|
||||||
|
|
|
@ -124,6 +124,7 @@ impl<'a> Renderer<'a> {
|
||||||
ignore_reason: reason.map(|s| s.to_string()),
|
ignore_reason: reason.map(|s| s.to_string()),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
self.builder,
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.builder.config.verbose_tests {
|
if self.builder.config.verbose_tests {
|
||||||
|
|
|
@ -1804,6 +1804,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the
|
||||||
|
|
||||||
cmd.arg("--channel").arg(&builder.config.channel);
|
cmd.arg("--channel").arg(&builder.config.channel);
|
||||||
|
|
||||||
|
if !builder.config.omit_git_hash {
|
||||||
|
cmd.arg("--git-hash");
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(commit) = builder.config.download_rustc_commit() {
|
if let Some(commit) = builder.config.download_rustc_commit() {
|
||||||
cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
|
cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,12 @@ pub fn prepare_tool_cargo(
|
||||||
cargo.env("CFG_VERSION", builder.rust_version());
|
cargo.env("CFG_VERSION", builder.rust_version());
|
||||||
cargo.env("CFG_RELEASE_NUM", &builder.version);
|
cargo.env("CFG_RELEASE_NUM", &builder.version);
|
||||||
cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
|
cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
|
||||||
|
if let Some(ref ver_date) = builder.rust_info().commit_date() {
|
||||||
|
cargo.env("CFG_VER_DATE", ver_date);
|
||||||
|
}
|
||||||
|
if let Some(ref ver_hash) = builder.rust_info().sha() {
|
||||||
|
cargo.env("CFG_VER_HASH", ver_hash);
|
||||||
|
}
|
||||||
|
|
||||||
let info = GitInfo::new(builder.config.omit_git_hash, &dir);
|
let info = GitInfo::new(builder.config.omit_git_hash, &dir);
|
||||||
if let Some(sha) = info.sha() {
|
if let Some(sha) = info.sha() {
|
||||||
|
|
|
@ -88,13 +88,16 @@ fn Foo() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be
|
These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be
|
||||||
rendered as `Foo`.
|
rendered as `Foo`. The following prefixes are available: `struct`, `enum`, `trait`, `union`,
|
||||||
|
`mod`, `module`, `const`, `constant`, `fn`, `function`, `method`, `derive`, `type`, `value`,
|
||||||
|
`macro`, `prim` or `primitive`.
|
||||||
|
|
||||||
You can also disambiguate for functions by adding `()` after the function name,
|
You can also disambiguate for functions by adding `()` after the function name,
|
||||||
or for macros by adding `!` after the macro name:
|
or for macros by adding `!` after the macro name. The macro `!` can be followed by `()`, `{}`,
|
||||||
|
or `[]`. Example:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
/// This is different from [`foo!`]
|
/// This is different from [`foo!()`].
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
|
|
||||||
/// This is different from [`foo()`]
|
/// This is different from [`foo()`]
|
||||||
|
|
|
@ -1419,6 +1419,7 @@ impl Disambiguator {
|
||||||
if let Some(idx) = link.find('@') {
|
if let Some(idx) = link.find('@') {
|
||||||
let (prefix, rest) = link.split_at(idx);
|
let (prefix, rest) = link.split_at(idx);
|
||||||
let d = match prefix {
|
let d = match prefix {
|
||||||
|
// If you update this list, please also update the relevant rustdoc book section!
|
||||||
"struct" => Kind(DefKind::Struct),
|
"struct" => Kind(DefKind::Struct),
|
||||||
"enum" => Kind(DefKind::Enum),
|
"enum" => Kind(DefKind::Enum),
|
||||||
"trait" => Kind(DefKind::Trait),
|
"trait" => Kind(DefKind::Trait),
|
||||||
|
@ -1437,6 +1438,7 @@ impl Disambiguator {
|
||||||
Ok(Some((d, &rest[1..], &rest[1..])))
|
Ok(Some((d, &rest[1..], &rest[1..])))
|
||||||
} else {
|
} else {
|
||||||
let suffixes = [
|
let suffixes = [
|
||||||
|
// If you update this list, please also update the relevant rustdoc book section!
|
||||||
("!()", DefKind::Macro(MacroKind::Bang)),
|
("!()", DefKind::Macro(MacroKind::Bang)),
|
||||||
("!{}", DefKind::Macro(MacroKind::Bang)),
|
("!{}", DefKind::Macro(MacroKind::Bang)),
|
||||||
("![]", DefKind::Macro(MacroKind::Bang)),
|
("![]", DefKind::Macro(MacroKind::Bang)),
|
||||||
|
|
|
@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
|
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
|
use rustc_span::hygiene::MacroKind;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
|
||||||
inside_public_path: bool,
|
inside_public_path: bool,
|
||||||
exact_paths: DefIdMap<Vec<Symbol>>,
|
exact_paths: DefIdMap<Vec<Symbol>>,
|
||||||
modules: Vec<Module<'tcx>>,
|
modules: Vec<Module<'tcx>>,
|
||||||
|
is_importable_from_parent: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
|
@ -107,6 +109,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
inside_public_path: true,
|
inside_public_path: true,
|
||||||
exact_paths: Default::default(),
|
exact_paths: Default::default(),
|
||||||
modules: vec![om],
|
modules: vec![om],
|
||||||
|
is_importable_from_parent: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,19 +322,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
renamed: Option<Symbol>,
|
renamed: Option<Symbol>,
|
||||||
parent_id: Option<LocalDefId>,
|
parent_id: Option<LocalDefId>,
|
||||||
) {
|
) {
|
||||||
|
if self.is_importable_from_parent
|
||||||
|
// If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
|
||||||
|
// attribute can still be visible.
|
||||||
|
|| match item.kind {
|
||||||
|
hir::ItemKind::Impl(..) => true,
|
||||||
|
hir::ItemKind::Macro(_, MacroKind::Bang) => {
|
||||||
|
self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
{
|
||||||
self.modules
|
self.modules
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.items
|
.items
|
||||||
.insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
|
.insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_item_inner(
|
fn visit_item_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: &'tcx hir::Item<'_>,
|
item: &'tcx hir::Item<'_>,
|
||||||
renamed: Option<Symbol>,
|
renamed: Option<Symbol>,
|
||||||
import_id: Option<LocalDefId>,
|
import_id: Option<LocalDefId>,
|
||||||
) -> bool {
|
) {
|
||||||
debug!("visiting item {:?}", item);
|
debug!("visiting item {:?}", item);
|
||||||
let name = renamed.unwrap_or(item.ident.name);
|
let name = renamed.unwrap_or(item.ident.name);
|
||||||
let tcx = self.cx.tcx;
|
let tcx = self.cx.tcx;
|
||||||
|
@ -448,7 +463,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_foreign_item_inner(
|
fn visit_foreign_item_inner(
|
||||||
|
@ -485,9 +499,23 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
|
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
|
||||||
if self.visit_item_inner(i, None, None) {
|
self.visit_item_inner(i, None, None);
|
||||||
|
let new_value = if self.is_importable_from_parent {
|
||||||
|
matches!(
|
||||||
|
i.kind,
|
||||||
|
hir::ItemKind::Mod(..)
|
||||||
|
| hir::ItemKind::ForeignMod { .. }
|
||||||
|
| hir::ItemKind::Impl(..)
|
||||||
|
| hir::ItemKind::Trait(..)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Whatever the context, if it's an impl block, the items inside it can be used so they
|
||||||
|
// should be visible.
|
||||||
|
matches!(i.kind, hir::ItemKind::Impl(..))
|
||||||
|
};
|
||||||
|
let prev = mem::replace(&mut self.is_importable_from_parent, new_value);
|
||||||
walk_item(self, i);
|
walk_item(self, i);
|
||||||
}
|
self.is_importable_from_parent = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
|
fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
|
||||||
|
|
|
@ -303,6 +303,9 @@ pub struct Config {
|
||||||
/// The current Rust channel
|
/// The current Rust channel
|
||||||
pub channel: String,
|
pub channel: String,
|
||||||
|
|
||||||
|
/// Whether adding git commit information such as the commit hash has been enabled for building
|
||||||
|
pub git_hash: bool,
|
||||||
|
|
||||||
/// The default Rust edition
|
/// The default Rust edition
|
||||||
pub edition: Option<String>,
|
pub edition: Option<String>,
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,11 @@ pub(super) fn handle_needs(
|
||||||
condition: cache.x86_64_dlltool,
|
condition: cache.x86_64_dlltool,
|
||||||
ignore_reason: "ignored when dlltool for x86_64 is not present",
|
ignore_reason: "ignored when dlltool for x86_64 is not present",
|
||||||
},
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-git-hash",
|
||||||
|
condition: config.git_hash,
|
||||||
|
ignore_reason: "ignored when git hashes have been omitted for building",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let (name, comment) = match ln.split_once([':', ' ']) {
|
let (name, comment) = match ln.split_once([':', ' ']) {
|
||||||
|
|
|
@ -251,6 +251,16 @@ fn debugger() {
|
||||||
assert!(check_ignore(&config, "// ignore-lldb"));
|
assert!(check_ignore(&config, "// ignore-lldb"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn git_hash() {
|
||||||
|
let mut config = config();
|
||||||
|
config.git_hash = false;
|
||||||
|
assert!(check_ignore(&config, "// needs-git-hash"));
|
||||||
|
|
||||||
|
config.git_hash = true;
|
||||||
|
assert!(!check_ignore(&config, "// needs-git-hash"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sanitizers() {
|
fn sanitizers() {
|
||||||
let mut config = config();
|
let mut config = config();
|
||||||
|
|
|
@ -159,6 +159,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||||
.optflag("", "nocapture", "")
|
.optflag("", "nocapture", "")
|
||||||
.optflag("h", "help", "show this message")
|
.optflag("h", "help", "show this message")
|
||||||
.reqopt("", "channel", "current Rust channel", "CHANNEL")
|
.reqopt("", "channel", "current Rust channel", "CHANNEL")
|
||||||
|
.optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
|
||||||
.optopt("", "edition", "default Rust edition", "EDITION");
|
.optopt("", "edition", "default Rust edition", "EDITION");
|
||||||
|
|
||||||
let (argv0, args_) = args.split_first().unwrap();
|
let (argv0, args_) = args.split_first().unwrap();
|
||||||
|
@ -302,6 +303,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||||
rustfix_coverage: matches.opt_present("rustfix-coverage"),
|
rustfix_coverage: matches.opt_present("rustfix-coverage"),
|
||||||
has_tidy,
|
has_tidy,
|
||||||
channel: matches.opt_str("channel").unwrap(),
|
channel: matches.opt_str("channel").unwrap(),
|
||||||
|
git_hash: matches.opt_present("git-hash"),
|
||||||
edition: matches.opt_str("edition"),
|
edition: matches.opt_str("edition"),
|
||||||
|
|
||||||
cc: matches.opt_str("cc").unwrap(),
|
cc: matches.opt_str("cc").unwrap(),
|
||||||
|
|
7
tests/run-make/issue-107094/Makefile
Normal file
7
tests/run-make/issue-107094/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# needs-git-hash
|
||||||
|
|
||||||
|
include ../tools.mk
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(BARE_RUSTC) --version --verbose | $(CGREP) -i -e "commit-hash: [0-9a-f]{40}" "commit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"
|
||||||
|
$(BARE_RUSTDOC) --version --verbose | $(CGREP) -i -e "commit-hash: [0-9a-f]{40}" "commit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"
|
|
@ -1,6 +1,9 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
fn f() -> impl Sized {
|
fn f() -> impl Sized {
|
||||||
enum E { //~ ERROR
|
enum E {
|
||||||
V(E),
|
V(E),
|
||||||
}
|
}
|
||||||
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
error[E0072]: recursive type `f::E` has infinite size
|
|
||||||
--> $DIR/infinite-recursive-type-impl-trait.rs:2:5
|
|
||||||
|
|
|
||||||
LL | enum E {
|
|
||||||
| ^^^^^^
|
|
||||||
LL | V(E),
|
|
||||||
| - recursive without indirection
|
|
||||||
|
|
|
||||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
|
||||||
|
|
|
||||||
LL | V(Box<E>),
|
|
||||||
| ++++ +
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0072`.
|
|
64
tests/rustdoc/issue-110422-inner-private.rs
Normal file
64
tests/rustdoc/issue-110422-inner-private.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/110422>.
|
||||||
|
// This test ensures that inner items (except for implementations and macros)
|
||||||
|
// don't appear in documentation.
|
||||||
|
|
||||||
|
// compile-flags: --document-private-items
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
// @has 'foo/index.html'
|
||||||
|
// Checking there is no "trait" entry.
|
||||||
|
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 4
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants'
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Macros'
|
||||||
|
|
||||||
|
// @has - '//a[@href="fn.foo.html"]' 'foo'
|
||||||
|
fn foo() {
|
||||||
|
fn bar() {}
|
||||||
|
|
||||||
|
// @has - '//a[@class="macro"]' 'visible_macro'
|
||||||
|
// @!has - '//a[@class="macro"]' 'non_visible_macro'
|
||||||
|
// @has 'foo/macro.visible_macro.html'
|
||||||
|
// @!has 'foo/macro.non_visible_macro.html'
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! visible_macro {
|
||||||
|
() => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! non_visible_macro {
|
||||||
|
() => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has 'foo/index.html'
|
||||||
|
// @has - '//a[@href="struct.Bar.html"]' 'Bar'
|
||||||
|
struct Bar;
|
||||||
|
|
||||||
|
const BAR: i32 = {
|
||||||
|
// @!has - '//a[@href="fn.yo.html"]' 'yo'
|
||||||
|
// @!has 'foo/fn.yo.html'
|
||||||
|
fn yo() {}
|
||||||
|
|
||||||
|
// @!has 'foo/index.html' '//a[@href="trait.Foo.html"]' 'Foo'
|
||||||
|
// @!has 'foo/trait.Foo.html'
|
||||||
|
trait Foo {
|
||||||
|
fn babar() {}
|
||||||
|
}
|
||||||
|
impl Foo for Bar {}
|
||||||
|
|
||||||
|
// @has 'foo/struct.Bar.html'
|
||||||
|
// @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub(crate) fn foo()'
|
||||||
|
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
|
||||||
|
// We now check that the `Foo` trait is not documented nor visible on `Bar` page.
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Implementations'
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Auto Trait Implementations'
|
||||||
|
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Blanket Implementations'
|
||||||
|
// @!has - '//*[@href="trait.Foo.html#method.babar"]/*[@class="code-header"]' 'fn babar()'
|
||||||
|
impl Bar {
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue