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:
bors 2023-04-18 05:28:44 +00:00
commit 74864fa496
27 changed files with 244 additions and 70 deletions

View file

@ -3181,7 +3181,6 @@ dependencies = [
"rustc_index",
"rustc_macros",
"rustc_serialize",
"serde_json",
"smallvec",
"stable_deref_trait",
"stacker",

View file

@ -138,12 +138,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// 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, .. }) => {
lctx.is_in_trait_impl = of_trait.is_some();
}
_ => {}
};
if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
lctx.is_in_trait_impl = impl_.of_trait.is_some();
}
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),

View file

@ -21,7 +21,6 @@ rustc-hash = "1.1.0"
rustc_index = { path = "../rustc_index", package = "rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
serde_json = "1.0.59"
smallvec = { version = "1.8.1", features = [
"const_generics",
"union",

View file

@ -87,6 +87,7 @@ use crate::fx::FxHashMap;
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::error::Error;
use std::fmt::Display;
use std::fs;
use std::intrinsics::unlikely;
use std::path::Path;
@ -97,7 +98,6 @@ use std::time::{Duration, Instant};
pub use measureme::EventId;
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
use parking_lot::RwLock;
use serde_json::json;
use smallvec::SmallVec;
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(
what: &str,
dur: Duration,
@ -772,13 +797,10 @@ pub fn print_time_passes_entry(
) {
match format {
TimePassesFormat::Json => {
let json = json!({
"pass": what,
"time": dur.as_secs_f64(),
"rss_start": start_rss,
"rss_end": end_rss,
});
eprintln!("time: {json}");
let entry =
JsonTimePassesEntry { pass: what, time: dur.as_secs_f64(), start_rss, end_rss };
eprintln!(r#"time: {entry}"#);
return;
}
TimePassesFormat::Text => (),
@ -894,3 +916,6 @@ cfg_if! {
}
}
}
#[cfg(test)]
mod tests;

View 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}"#
)
}

View file

@ -3146,7 +3146,6 @@ impl<'hir> Item<'hir> {
(ty, gen)
}
/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
/// Expect an [`ItemKind::OpaqueTy`] or panic.
#[track_caller]
pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
@ -3168,7 +3167,6 @@ impl<'hir> Item<'hir> {
(data, gen)
}
/// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
/// Expect an [`ItemKind::Union`] or panic.
#[track_caller]
pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {

View file

@ -74,10 +74,9 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
let span = match tcx.hir().expect_item(impl_did).kind {
ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
ItemKind::Impl(impl_) => impl_.self_ty.span,
_ => bug!("expected Copy impl item"),
let span = match tcx.hir().expect_item(impl_did).expect_impl() {
hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
hir::Impl { self_ty, .. } => self_ty.span,
};
let cause = traits::ObligationCause::misc(span, impl_did);

View file

@ -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() {
let opaque_local_def_id = def_id.as_local();
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 {
hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
_ => bug!("The HirId comes from a `ty::Opaque`"),
}
tcx.hir().expect_item(opaque_local_def_id).expect_opaque_ty()
} else {
return false;
};

View file

@ -392,12 +392,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// defining scope.
#[instrument(skip(self), level = "trace", ret)]
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
match self.tcx.hir().expect_item(def_id).kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
ref itemkind => {
bug!("weird opaque type: {:?}, {:#?}", def_id, itemkind)
}
}
self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
}
}

View file

@ -1469,8 +1469,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match impl_item.kind {
ty::AssocKind::Fn => {
let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
let (sig, body) =
self.tcx.hir().expect_impl_item(def_id.expect_local()).expect_fn();
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));
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable

View file

@ -33,6 +33,14 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
}
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 =
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
trace!(?self, ?flags, ?res, "has_type_flags");

View file

@ -2030,7 +2030,7 @@ impl<'a> Builder<'a> {
}
#[cfg(feature = "build-metrics")]
self.metrics.enter_step(&step);
self.metrics.enter_step(&step, self);
let (out, dur) = {
let start = Instant::now();
@ -2056,7 +2056,7 @@ impl<'a> Builder<'a> {
}
#[cfg(feature = "build-metrics")]
self.metrics.exit_step();
self.metrics.exit_step(self);
{
let mut stack = self.stack.borrow_mut();

View file

@ -4,7 +4,7 @@
//! 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`.
use crate::builder::Step;
use crate::builder::{Builder, Step};
use crate::util::t;
use crate::Build;
use serde_derive::{Deserialize, Serialize};
@ -33,7 +33,12 @@ impl BuildMetrics {
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();
// 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();
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();
state
.running_steps

View file

@ -124,6 +124,7 @@ impl<'a> Renderer<'a> {
ignore_reason: reason.map(|s| s.to_string()),
},
},
self.builder,
);
if self.builder.config.verbose_tests {

View file

@ -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);
if !builder.config.omit_git_hash {
cmd.arg("--git-hash");
}
if let Some(commit) = builder.config.download_rustc_commit() {
cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
}

View file

@ -194,6 +194,12 @@ pub fn prepare_tool_cargo(
cargo.env("CFG_VERSION", builder.rust_version());
cargo.env("CFG_RELEASE_NUM", &builder.version);
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);
if let Some(sha) = info.sha() {

View file

@ -88,13 +88,16 @@ fn Foo() {}
```
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,
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
/// This is different from [`foo!`]
/// This is different from [`foo!()`].
fn foo() {}
/// This is different from [`foo()`]

View file

@ -1419,6 +1419,7 @@ impl Disambiguator {
if let Some(idx) = link.find('@') {
let (prefix, rest) = link.split_at(idx);
let d = match prefix {
// If you update this list, please also update the relevant rustdoc book section!
"struct" => Kind(DefKind::Struct),
"enum" => Kind(DefKind::Enum),
"trait" => Kind(DefKind::Trait),
@ -1437,6 +1438,7 @@ impl Disambiguator {
Ok(Some((d, &rest[1..], &rest[1..])))
} else {
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)),

View file

@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
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::Span;
@ -87,6 +88,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
inside_public_path: bool,
exact_paths: DefIdMap<Vec<Symbol>>,
modules: Vec<Module<'tcx>>,
is_importable_from_parent: bool,
}
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@ -107,6 +109,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
inside_public_path: true,
exact_paths: Default::default(),
modules: vec![om],
is_importable_from_parent: true,
}
}
@ -319,11 +322,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
renamed: Option<Symbol>,
parent_id: Option<LocalDefId>,
) {
self.modules
.last_mut()
.unwrap()
.items
.insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
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
.last_mut()
.unwrap()
.items
.insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
}
}
fn visit_item_inner(
@ -331,7 +346,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
item: &'tcx hir::Item<'_>,
renamed: Option<Symbol>,
import_id: Option<LocalDefId>,
) -> bool {
) {
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
let tcx = self.cx.tcx;
@ -448,7 +463,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
}
}
true
}
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>) {
if self.visit_item_inner(i, None, None) {
walk_item(self, i);
}
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);
self.is_importable_from_parent = prev;
}
fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {

View file

@ -303,6 +303,9 @@ pub struct Config {
/// The current Rust channel
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
pub edition: Option<String>,

View file

@ -115,6 +115,11 @@ pub(super) fn handle_needs(
condition: cache.x86_64_dlltool,
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([':', ' ']) {

View file

@ -251,6 +251,16 @@ fn debugger() {
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]
fn sanitizers() {
let mut config = config();

View file

@ -159,6 +159,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
.optflag("", "nocapture", "")
.optflag("h", "help", "show this message")
.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");
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"),
has_tidy,
channel: matches.opt_str("channel").unwrap(),
git_hash: matches.opt_present("git-hash"),
edition: matches.opt_str("edition"),
cc: matches.opt_str("cc").unwrap(),

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

View file

@ -1,6 +1,9 @@
// check-pass
fn f() -> impl Sized {
enum E { //~ ERROR
enum E {
V(E),
}
unimplemented!()
}

View file

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

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