Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove a few actually_rustdoc uses #107289

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
if !tcx.is_closure(did.to_def_id())
&& tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
{
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
if tcx.sess.target.is_like_wasm {
// The `#[target_feature]` attribute is allowed on
// WebAssembly targets on all functions, including safe
// ones. Other targets require that `#[target_feature]` is
Expand All @@ -282,10 +282,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
// deterministic trap. There is no undefined behavior when
// executing WebAssembly so `#[target_feature]` is allowed
// on safe functions (but again, only for WebAssembly)
//
// Note that this is also allowed if `actually_rustdoc` so
// if a target is documenting some wasm-specific code then
// it's not spuriously denied.
} else if !tcx.features().target_feature_11 {
let mut err = feature_err(
&tcx.sess.parse_sess,
Expand Down
29 changes: 1 addition & 28 deletions compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,24 +293,6 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[

const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];

/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> {
std::iter::empty()
.chain(ARM_ALLOWED_FEATURES.iter())
.chain(AARCH64_ALLOWED_FEATURES.iter())
.chain(X86_ALLOWED_FEATURES.iter())
.chain(HEXAGON_ALLOWED_FEATURES.iter())
.chain(POWERPC_ALLOWED_FEATURES.iter())
.chain(MIPS_ALLOWED_FEATURES.iter())
.chain(RISCV_ALLOWED_FEATURES.iter())
.chain(WASM_ALLOWED_FEATURES.iter())
.chain(BPF_ALLOWED_FEATURES.iter())
.cloned()
}

pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
match &*sess.target.arch {
"arm" => ARM_ALLOWED_FEATURES,
Expand Down Expand Up @@ -462,16 +444,7 @@ pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
supported_target_features: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
if tcx.sess.opts.actually_rustdoc {
// rustdoc needs to be able to document functions that use all the features, so
// whitelist them all
all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
} else {
supported_target_features(tcx.sess)
.iter()
.map(|&(a, b)| (a.to_string(), b))
.collect()
}
supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
},
asm_target_features,
..*providers
Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ impl Drop for HandlerInner {
self.emit_stashed_diagnostics();

if !self.has_errors() {
let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new());
let bugs = std::mem::take(&mut self.delayed_span_bugs);
self.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
}

Expand All @@ -521,7 +521,7 @@ impl Drop for HandlerInner {
// lints can be `#[allow]`'d, potentially leading to this triggering.
// Also, "good path" should be replaced with a better naming.
if !self.has_any_message() && !self.suppressed_expected_diag {
let bugs = std::mem::replace(&mut self.delayed_good_path_bugs, Vec::new());
let bugs = std::mem::take(&mut self.delayed_good_path_bugs);
self.flush_delayed(
bugs,
"no warnings or errors encountered even though `delayed_good_path_bugs` issued",
Expand Down Expand Up @@ -661,6 +661,19 @@ impl Handler {
inner.stashed_diagnostics = Default::default();
}

/// Avoid failing compilation in the presence of delayed bugs.
///
/// NOTE: *do not* call this function from rustc. It is only meant to be called from rustdoc.
/// Rustdoc documents multiple targets at once, meaning there may be multiple versions
/// of the same function in scope at the same time, which isn't legal Rust otherwise. See
/// <https://doc.rust-lang.org/beta/rustdoc/advanced-features.html#interactions-between-platform-specific-docs>
/// for details
pub fn reset_delayed_bugs(&self) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn reset_delayed_bugs(&self) {
pub fn reset_delayed_bugs(&self) {
assert!(self.opts.actually_rustdoc);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆 I want to remove that flag at some point

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to still keep a record of the fact that there was a delayed bug and if so ICE when using sess.compile_error() but ignore this flag when using a new sess.compile_error_allow_reset_delay_bugs() to be used in rustdoc? Or maybe even have that later method be the method that is actually responsible for ignoring delayed bugs?

let mut inner = self.inner.borrow_mut();
inner.delayed_span_bugs = Default::default();
inner.delayed_good_path_bugs = Default::default();
}

/// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
/// Retrieve a stashed diagnostic with `steal_diagnostic`.
pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
Expand Down Expand Up @@ -1231,7 +1244,7 @@ impl Handler {

pub fn flush_delayed(&self) {
let mut inner = self.inner.lock();
let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new());
let bugs = std::mem::take(&mut inner.delayed_span_bugs);
inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
}
}
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
return;
};

// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
// `async-std` (and `pub async fn` in general).
// Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
// See https://github.com/rust-lang/rust/issues/75100
if tcx.sess.opts.actually_rustdoc {
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there tests for this code path? If not, can you please double check that documenting async-std still works after this change? Make sure to enable all the features enabled on doc's.rs (you can use doc-like-docs.rs in @Nemo157 's dotfiles).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there are tests. I'll run the try build on async-std once it finishes. Seems like rustup toolchain link on local builds doesn't work for rustdoc as cargo +linked_thingy doc can't find libcore and libstd

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should work - try x build rustdoc library, or just x build without arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm weird, not sure what I was doing wrong before.

It passes fine now with --all-features

}

let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id());
let span = tcx.def_span(item.owner_id.def_id);

Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,11 +692,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// The interface is empty.
hir::ItemKind::GlobalAsm(..) => {}
hir::ItemKind::OpaqueTy(ref opaque) => {
// HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
// Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
// mark this as unreachable.
// See https://github.com/rust-lang/rust/issues/75100
if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc {
if !opaque.in_trait {
// FIXME: This is some serious pessimization intended to workaround deficiencies
// in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
// reachable if they are returned via `impl Trait`, even from private functions.
Expand Down
24 changes: 8 additions & 16 deletions compiler/rustc_trait_selection/src/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
Expand Down Expand Up @@ -313,14 +309,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
Expand Down
40 changes: 27 additions & 13 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::json::JsonEmitter;
use rustc_feature::UnstableFeatures;
use rustc_hir::def::{Namespace, Res};
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Path, TraitCandidate};
use rustc_interface::interface;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_resolve as resolve;
use rustc_session::config::{self, CrateType, ErrorOutputType};
Expand All @@ -22,7 +23,6 @@ use rustc_span::{source_map, Span, Symbol};
use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
use std::sync::LazyLock;

use crate::clean::inline::build_external_trait;
use crate::clean::{self, ItemId};
Expand Down Expand Up @@ -283,11 +283,10 @@ pub(crate) fn create_config(
providers.lint_mod = |_, _| {};
// Prevent `rustc_hir_analysis::check_crate` from calling `typeck` on all bodies.
providers.typeck_item_bodies = |_, _| {};
providers.check_mod_item_types =
|_, _| panic!("check_mod_item_types should not get called at all in rustdoc");
// hack so that `used_trait_imports` won't try to call typeck
providers.used_trait_imports = |_, _| {
static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
&EMPTY_SET
};
providers.used_trait_imports = |_, _| Box::leak(Box::new(UnordSet::default()));
// In case typeck does end up being called, don't ICE in case there were name resolution errors
providers.typeck = move |tcx, def_id| {
// Closures' tables come from their outermost function,
Expand All @@ -304,6 +303,27 @@ pub(crate) fn create_config(
EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
(rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
};
providers.type_of = |tcx, def_id| {
let did = def_id.expect_local();
use rustc_hir::*;

let hir_id = tcx.hir().local_def_id_to_hir_id(did);

match tcx.hir().get(hir_id) {
Node::Item(item) => match item.kind {
ItemKind::OpaqueTy(_) => return tcx.ty_error(),
_ => {}
},
_ => {}
}
(rustc_interface::DEFAULT_QUERY_PROVIDERS.type_of)(tcx, def_id)
};
providers.codegen_fn_attrs = |_, did| {
assert!(did.is_local());
CodegenFnAttrs::new()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this right? Won't it end up in us failing to include the target features in the generated docs?

cc @Amanieu , I'm not sure if this has tests.

};
providers.supported_target_features =
|_, _| panic!("supported_target_features should not get called by rustdoc");
}),
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
Expand All @@ -326,14 +346,8 @@ pub(crate) fn run_global_ctxt(
// typeck function bodies or run the default rustc lints.
// (see `override_queries` in the `config`)

// HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
// HACK(jynelson) this calls an _extremely_ limited subset of what the `analysis` query does
// and might break if queries change their assumptions in the future.

// NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
tcx.sess.time("item_types_checking", || {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
Comment on lines -333 to -335
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The performance improvement is almost entirely due to this change. We stop checking item signatures.

tcx.sess.abort_if_errors();
tcx.sess.time("missing_docs", || {
rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
});
Expand Down
8 changes: 7 additions & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,12 @@ fn main_args(at_args: &[String]) -> MainResult {
}),
}
})
})
})?;
// than ICEing. Rustdoc documents multiple targets at once, meaning there may be multiple versions
// of the same function in scope at the same time, which isn't legal Rust otherwise. See
// https://doc.rust-lang.org/beta/rustdoc/advanced-features.html#interactions-between-platform-specific-docs
// for details
sess.diagnostic().reset_delayed_bugs();
Ok(())
})
}
3 changes: 2 additions & 1 deletion tests/rustdoc-ui/issue-79494.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// only-x86_64-unknown-linux-gnu
// check-pass

#![feature(const_transmute)]

const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; //~ ERROR cannot transmute between types of different sizes, or dependently-sized types
const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make this public to force it to be evaluated? Otherwise #79494 could regress for documented items.

12 changes: 0 additions & 12 deletions tests/rustdoc-ui/issue-79494.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// should-fail

#![allow(unused)]

// check-pass

trait Foo<T>: Sized {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this needs to be public too?

fn bar(i: i32, t: T, s: &Self) -> (T, i32);
}

impl Foo<usize> for () {
fn bar(i: _, t: _, s: _) -> _ {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
(1, 2)
}
}
Expand Down
6 changes: 1 addition & 5 deletions tests/rustdoc-ui/track-diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
// compile-flags: -Z track-diagnostics
// error-pattern: created at

// Normalize the emitted location so this doesn't need
// updating everytime someone adds or removes a line.
// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
// check-pass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This no longer tests -Ztrack-diagnostics.


struct A;
struct B;
Expand Down
10 changes: 0 additions & 10 deletions tests/rustdoc-ui/track-diagnostics.stderr

This file was deleted.